fjocke
asked on
C# Regex out a number from a string and then divide it
item_make_list={} corpse_make_list={{[cokaco la];5;5;5. 6617};{[re dbul];1;1; 100};{[moo n];1;1;22. 6465}} additional_make_list={}add itional_ma ke_multi_l ist={{{{[k ebab];150; 210;100}}; 70};{{{[ke bab_meat]; 1;1;30.985 9};{[kebab _magic];1; 1;23.0047} ;{[magic_k ebab];1;1; 46.0094}}; 100};{{{[s auce];5;5; 5.82524};{ [roster];5 ;5;2.91262 };{[whiske y];5;5;1.9 4174};{[cl aymore];5; 5;1.16504} ;{[rocket] ;5;5;5.825 24};{[mous e];1;1;11. 6506}};33. 494}}";
What i want todo, is using regex to get out certain values and then divide them or multiply them.
For instance if i write it like this:
string txt = "item_make_list={} corpse_make_list={{[cokaco la];5;5;5. 6617};{[re dbul];1;1; 100};{[moo n];1;1;22. 6465}} additional_make_list={}add itional_ma ke_multi_l ist={{{{[k ebab];150; 210;100}}; 70};{{{[ke bab_meat]; 1;1;30.985 9};{[kebab _magic];1; 1;23.0047} ;{[magic_k ebab];1;1; 46.0094}}; 100};{{{[s auce];5;5; 5.82524};{ [roster];5 ;5;2.91262 };{[whiske y];5;5;1.9 4174};{[cl aymore];5; 5;1.16504} ;{[rocket] ;5;5;5.825 24};{[mous e];1;1;11. 6506}};33. 494}}";
Regex regex = new Regex("([-+]?\\d+)", RegexOptions.IgnoreCase | RegexOptions.Singleline);
string result = regex.Replace(txt, "6");//new MatchEvaluator (Replacement));
listBox2.Items.Add(result) ;
It will replace all the int values with 6 in the string. But what i want todo is to firstly pick out everything that comes after a ; and then either divide them or multiply them depending on what.
And if its a float value like 5.6617 it should take the full value and multiply or divide it.
So, how do i make the value picked out by regex into a int, divide it or multiply it and then press it back in again?
Thanks
What i want todo, is using regex to get out certain values and then divide them or multiply them.
For instance if i write it like this:
string txt = "item_make_list={} corpse_make_list={{[cokaco
Regex regex = new Regex("([-+]?\\d+)", RegexOptions.IgnoreCase | RegexOptions.Singleline);
string result = regex.Replace(txt, "6");//new MatchEvaluator (Replacement));
listBox2.Items.Add(result)
It will replace all the int values with 6 in the string. But what i want todo is to firstly pick out everything that comes after a ; and then either divide them or multiply them depending on what.
And if its a float value like 5.6617 it should take the full value and multiply or divide it.
So, how do i make the value picked out by regex into a int, divide it or multiply it and then press it back in again?
Thanks
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
There is still one thing you missed, the actual thing to get out only numbers that comes after a ;
Cause the string example i gave, was only a small part of the actual string.
So the regex needs a look-over aswell, if you would be so kind :)
Regards
Jocke
Cause the string example i gave, was only a small part of the actual string.
So the regex needs a look-over aswell, if you would be so kind :)
Regards
Jocke
Given this string what do you want the results to look like?
string txt = "item_make_list={} corpse_make_list={{[cokaco la];5;5;5. 6617}"
string txt = "item_make_list={} corpse_make_list={{[cokaco
ASKER
Either it should replace out each INT that comes after a ; alone, or a };
So instance
;7 should be multiplied with 2 = ;14
or if its };2 multi 4 = };8
So a regex for either replacing only numbers that comes after a ; or };
Actually it would be the best if it could check wether its between two { } brackets aswell.
So instance
;7 should be multiplied with 2 = ;14
or if its };2 multi 4 = };8
So a regex for either replacing only numbers that comes after a ; or };
Actually it would be the best if it could check wether its between two { } brackets aswell.
So if I understand you so far if an integer value follows a semicolon such as ;7 you always want to multiply the value by 2 and replace the value 7 in this case with the value 14 in the string.
If an integer value follows a right curly bracket followed by a semicolon such as };2 you always want to multiply the value by 4 and replace the value 2 in this case with the value 8 in the string.
All other integers do not get modified.
How about float values such as this from your example string, "{[whiskey];5;5;1.94174}", does the value, ;1.94174, get modified? If so how?
To your last statement, "Actually it would be the best if it could check wether its between two { } brackets aswell.", if it is between to { } such as in this case, "{[whiskey];5;5;1.94174}", what needs to be done?
In order to write a regex pattern I need to know the exact patterns to look for and what to do with them when they are found.
If an integer value follows a right curly bracket followed by a semicolon such as };2 you always want to multiply the value by 4 and replace the value 2 in this case with the value 8 in the string.
All other integers do not get modified.
How about float values such as this from your example string, "{[whiskey];5;5;1.94174}",
To your last statement, "Actually it would be the best if it could check wether its between two { } brackets aswell.", if it is between to { } such as in this case, "{[whiskey];5;5;1.94174}",
In order to write a regex pattern I need to know the exact patterns to look for and what to do with them when they are found.
ASKER
npc_begin warrior 20021 [gravel] level=14 acquire_exp_rate=12.726 acquire_sp=95 unsowing=0 clan={-1} ignore_clan_list={} clan_help_range=300 slot_chest=[] slot_rhand=[] slot_lhand=[] shield_defense_rate=0 shield_defense=0 skill_list={@s_gender_spok e} npc_ai={[gravel];{[AfterSh ave]=100}; {[AfterSha ve1]=100}; {[AfterSha ve2]=100}} category={} race=animal sex=male undying=0 can_be_attacked=1 corpse_time=7 no_sleep_mode=0 agro_range=1000 ground_high={110;0;0} ground_low={40;0;0} exp=191455 org_hp=230.38548 org_hp_regen=2.5 org_mp=140.88 org_mp_regen=1.2 collision_radius={21;21} collision_height={40;40} str=40 int=21 dex=30 wit=20 con=43 men=10 base_attack_type=sword base_attack_range=40 base_damage_range={0;0;80; 120} base_rand_dam=30 base_physical_attack=29.97 1106 base_critical=4 physical_hit_modify=4.75 base_attack_speed=253 base_reuse_delay=0 base_magic_attack=18.6058 base_defend=64.61980909090 91 base_magic_defend=52.01457 physical_avoid_modify=0 soulshot_count=0 spiritshot_count=0 hit_time_factor=0.34 item_make_list={} corpse_make_list={{[beerca n];1;1;8.1 94};{[wate r_bottle]; 1;1;71.897 5};{[stick _of_doom]; 1;1;8.194} } additional_make_list={} additional_make_multi_list ={{{{[icec ream];570; 840;100}}; 70};{{{[ba nana];1;1; 7.9838};{[ apple_scru tt];1;1;84 .0323};{[l olipop];1; 1;7.9839}} ;1.016};{{ {[mort];5; 5;3.84422} ;{[sail];5 ;5;3.84422 };{[pillow ];1;1;18.8 442};{[car box];1;1;4 2.7136}};8 5.6295}} hp_increase=0 mp_increase=0 safe_height=100 npc_end
This is a ful length string.
There are sevral tousends of this line with diffrent values.
So since there are more values that starts with a ;
we'll first have to notice wether its in between corpse_make_list={} or additional_make_list={} or additional_make_multi_list ={}
if it is, it should multiply or divide the the number chosen for instance, i might just want to mulitply the
70 in {{{[icecream];570;840;100} };70} with two. so then i guess we have to get a regex that takes out the number that has a }; before it for that to happend. Sometime i might have to only change the values ;570;840;100 in {{{[icecream];570;840;100} };70} and hence somehow take out only those values and multiply or divide them, does this make more sense to you?
This is a ful length string.
There are sevral tousends of this line with diffrent values.
So since there are more values that starts with a ;
we'll first have to notice wether its in between corpse_make_list={} or additional_make_list={} or additional_make_multi_list
if it is, it should multiply or divide the the number chosen for instance, i might just want to mulitply the
70 in {{{[icecream];570;840;100}
We need to set up the rules:
The only values to be modified are those values that are in one of the following three markers:
A) corpse_make_list={}
B) additional_make_list={}
C) additional_make_multi_list ={}
For example: corpse_make_list={{[cokaco la];5;5;5. 6617};
Questions:
1. In the example I gave above how do you determine where the end of the marker? For example the sample starts with this corpse_make_list={{[ and I selected the first }; as its end, is that correct?
2. Inside the marker there are multiple values. How do you determine which value will be modified?
3. You state that the, "if it is, it should multiply or divide the the number chosen", So how do you determine to multiply or divide?
The only values to be modified are those values that are in one of the following three markers:
A) corpse_make_list={}
B) additional_make_list={}
C) additional_make_multi_list
For example: corpse_make_list={{[cokaco
Questions:
1. In the example I gave above how do you determine where the end of the marker? For example the sample starts with this corpse_make_list={{[ and I selected the first }; as its end, is that correct?
2. Inside the marker there are multiple values. How do you determine which value will be modified?
3. You state that the, "if it is, it should multiply or divide the the number chosen", So how do you determine to multiply or divide?
ASKER
1. Yes, the coprise_make_list={ will always end with a }
2. Im not really sure, but i guess id need to be able to modify both.
[cokacola];5;5;5.6617
Here it would be like this:
First ;5, Min chance for cocacola to drop as item
Sencond ;5, max change for cocacola to drop as item
Third ; the chance for this specific item to drop at all.
So what we could do i guess is to count the number of ; in between { }
And if i set 1 in the input counter, it will for instance multiply the first 5 with a chosen value.
If i specify 3 in the input counter (which counts ;) it will take 5.6617 and multiply it with a chosen value.
3. I just want to pick that out for myself, what we have now is what i want, just want to specify if i want to multiply the regexed integer with a chosen value, OR i will just change so that i divide it.
Its just userinputed and the code you made this far is exactly as how i want it, just comment out if i want divide instead of multiply.
2. Im not really sure, but i guess id need to be able to modify both.
[cokacola];5;5;5.6617
Here it would be like this:
First ;5, Min chance for cocacola to drop as item
Sencond ;5, max change for cocacola to drop as item
Third ; the chance for this specific item to drop at all.
So what we could do i guess is to count the number of ; in between { }
And if i set 1 in the input counter, it will for instance multiply the first 5 with a chosen value.
If i specify 3 in the input counter (which counts ;) it will take 5.6617 and multiply it with a chosen value.
3. I just want to pick that out for myself, what we have now is what i want, just want to specify if i want to multiply the regexed integer with a chosen value, OR i will just change so that i divide it.
Its just userinputed and the code you made this far is exactly as how i want it, just comment out if i want divide instead of multiply.
Hi fjocke;
The regex pattern to modify the data is in the posted sample code below. You will need to modify the event handler DivideMultiplyValue to modify the data to meet your needs. Note that the event handler signature can not be modified to send additional parameters. Any values you need to pass into it must be done before calling the Regex.Replace function as I did with the value of multDivBy.
Fernando
The regex pattern to modify the data is in the posted sample code below. You will need to modify the event handler DivideMultiplyValue to modify the data to meet your needs. Note that the event handler signature can not be modified to send additional parameters. Any values you need to pass into it must be done before calling the Regex.Replace function as I did with the value of multDivBy.
Fernando
private void button1_Click(object sender, EventArgs e)
{
// Sample Data
string txt = "npc_begin warrior 20021 [gravel] level=14 acquire_exp_rate=12.726 acquire_sp=95 unsowing=0 clan={-1} ignore_clan_list={} clan_help_range=300 slot_chest=[] slot_rhand=[] slot_lhand=[] shield_defense_rate=0 shield_defense=0 skill_list={@s_gender_spoke} npc_ai={[gravel];{[AfterShave]=100};{[AfterShave1]=100};{[AfterShave2]=100}} category={} race=animal sex=male undying=0 can_be_attacked=1 corpse_time=7 no_sleep_mode=0 agro_range=1000 ground_high={110;0;0} ground_low={40;0;0} exp=191455 org_hp=230.38548 org_hp_regen=2.5 org_mp=140.88 org_mp_regen=1.2 collision_radius={21;21} collision_height={40;40} str=40 int=21 dex=30 wit=20 con=43 men=10 base_attack_type=sword base_attack_range=40 base_damage_range={0;0;80;120} base_rand_dam=30 base_physical_attack=29.971106 base_critical=4 physical_hit_modify=4.75 base_attack_speed=253 base_reuse_delay=0 base_magic_attack=18.6058 base_defend=64.6198090909091 base_magic_defend=52.01457 physical_avoid_modify=0 soulshot_count=0 spiritshot_count=0 hit_time_factor=0.34 item_make_list={} corpse_make_list={{[beercan];1;1;8.194};{[water_bottle];1;1;71.8975};{[stick_of_doom];1;1;8.194}} additional_make_list={} additional_make_multi_list={{{{[icecream];570;840;100}};70};{{{[banana];1;1;7.9838};{[apple_scrutt];1;1;84.0323};{[lolipop];1;1;7.9839}};1.016};{{{[mort];5;5;3.84422};{[sail];5;5;3.84422};{[pillow];1;1;18.8442};{[carbox];1;1;42.7136}};85.6295}} hp_increase=0 mp_increase=0 safe_height=100 npc_end";
// Regex pattern
string pattern = @"((?:(corpse_make_list=\{|additional_make_multi_list=\{|additional_make_list=\{)((?=[^}]).*?)(?:;(\d+\.?\d*?))+}))";
// Create the Regex Object with the above pattern
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
// Test value to do the multiply or divide on the data
multDivBy = 5; // Divide or Multiply values by this number
// Replace the data in the string with the new values returned from Regex
string result = regex.Replace(txt, new MatchEvaluator(DivideMultiplyValue));
//listBox2.Items.Add(result);
textBox1.Text = result;
}
// Define the test value to do the multiply or divide on the data
private int multDivBy;
// Regex calls this event handler to modify the data and send the replacement string back
private string DivideMultiplyValue(Match m)
{
// The following string has the value of
// corpse_make_list=, additional_make_list=, or additional_make_multi_list=
String name = m.Groups[2].Value;
// The characters between ={ and the first digit
String chars = m.Groups[3].Value;
// The next three string values
String value1 = m.Groups[4].Captures[0].Value;
String value2 = m.Groups[4].Captures[1].Value;
String value3 = m.Groups[4].Captures[2].Value;
String mod1 = String.Empty;
String mod2 = String.Empty;
String mod3 = String.Empty;
// Return this string to regex to replace the string sent into this function
String replaceWith = String.Empty;
// First Value
if (value1.Contains("."))
{
// It is a float
double dblValue = Convert.ToDouble(value1);
// Divide or Multiply dblValue here
//dblValue *= multDivBy;
dblValue /= multDivBy;
mod1 = dblValue.ToString();
}
else
{
// It is an integer
int intValue = Convert.ToInt32(value1);
// Divide or Multiply dblValue here
//intValue *= multDivBy;
intValue /= multDivBy;
mod1 = intValue.ToString();
}
// Second Value
if (value2.Contains("."))
{
// It is a float
double dblValue = Convert.ToDouble(value2);
// Divide or Multiply dblValue here
//dblValue *= multDivBy;
dblValue /= multDivBy;
mod2 = dblValue.ToString();
}
else
{
// It is an integer
int intValue = Convert.ToInt32(value2);
// Divide or Multiply dblValue here
//intValue *= multDivBy;
intValue /= multDivBy;
mod2 = intValue.ToString();
}
// Third Value
if (value3.Contains("."))
{
// It is a float
double dblValue = Convert.ToDouble(value3);
// Divide or Multiply dblValue here
//dblValue *= multDivBy;
dblValue /= multDivBy;
mod3 = dblValue.ToString();
}
else
{
// It is an integer
int intValue = Convert.ToInt32(value3);
// Divide or Multiply dblValue here
//intValue *= multDivBy;
intValue /= multDivBy;
mod3 = intValue.ToString();
}
replaceWith = name + chars + ";" + mod1 + ";" + mod2 + ";" + mod3 + "}";
return replaceWith;
}
ASKER
Im trying to fix an exception getting thrown at me.
Saying "Input string was not in correct format" im using VS 2005 Pro.
It gets thrown at:
if (value3.Contains("."))
{
// It is a float
double dblValue = Convert.ToDouble(value3); <-- HERE
// Divide or Multiply dblValue here
//dblValue *= multDivBy;
dblValue /= multDivBy;
mod3 = dblValue.ToString();
}
else
Im not certain why that only happens there? >>
Saying "Input string was not in correct format" im using VS 2005 Pro.
It gets thrown at:
if (value3.Contains("."))
{
// It is a float
double dblValue = Convert.ToDouble(value3); <-- HERE
// Divide or Multiply dblValue here
//dblValue *= multDivBy;
dblValue /= multDivBy;
mod3 = dblValue.ToString();
}
else
Im not certain why that only happens there? >>
ASKER
Allright i solved that with a:
System.Threading.Thread.Cu rrentThrea d.CurrentC ulture = new System.Globalization.Cultu reInfo("en -US");
The regex is nice, however it seems to be only working on the first selection in the items list, when i say that i mean:
Orginal string:
item_make_list={} corpse_make_list={{[beerca n];1;1;8.1 94};{[wate r_bottle]; 1;1;71.897 5};{[stick _of_doom]; 1;1;8.194} } additional_make_list={} additional_make_multi_list ={{{{[icec ream];570; 840;100}}; 70};{{{[ba nana];1;1; 7.9838};{[ apple_scru tt];1;1;84 .0323};{[l olipop];1; 1;7.9839}} ;1.016};{{ {[mort];5; 5;3.84422} ;{[sail];5 ;5;3.84422 };{[pillow ];1;1;18.8 442};{[car box];1;1;4 2.7136}};8 5.6295}}
If you compare it to our current result:
item_make_list={} corpse_make_list={{[beerca n];2;2;16. 388};{[wat er_bottle] ;1;1;71.89 75};{[stic k_of_doom] ;1;1;8.194 }} additional_make_list={} additional_make_multi_list ={{{{[icec ream];1140 ;1680;200} };70};{{{[ banana];1; 1;7.9838}; {[apple_sc rutt];1;1; 84.0323};{ [lolipop]; 1;1;7.9839 }};1.016}; {{{[mort]; 5;5;3.8442 2};{[sail] ;5;5;3.844 22};{[pill ow];1;1;18 .8442};{[c arbox];1;1 ;42.7136}} ;85.6295}}
you see only the first instance after each and every new coprse_make_list or item_make_ist or additiional_make_multi_lis t gets (in this case multiplied by two) We want this to happen on every item.
If you know a good way test or get a good regexp up running im not shy to try look at it myself.
If you have a good way to test it and build it, please let me know.
You've been very helpful this far, feel free to walk away :)
System.Threading.Thread.Cu
The regex is nice, however it seems to be only working on the first selection in the items list, when i say that i mean:
Orginal string:
item_make_list={} corpse_make_list={{[beerca
If you compare it to our current result:
item_make_list={} corpse_make_list={{[beerca
you see only the first instance after each and every new coprse_make_list or item_make_ist or additiional_make_multi_lis
If you know a good way test or get a good regexp up running im not shy to try look at it myself.
If you have a good way to test it and build it, please let me know.
You've been very helpful this far, feel free to walk away :)
I had asked you a couple of post back the question:
The only values to be modified are those values that are in one of the following three markers:
A) corpse_make_list={}
B) additional_make_list={}
C) additional_make_multi_list ={}
because you had stated that, "we'll first have to notice wether its in between corpse_make_list={} or additional_make_list={} or additional_make_multi_list ={}".
In order to write a Regex expression the rules must be identified to know what exactly needs to be matched so that a pattern can be developed for that specific pattern. The the first thing that needs to be done is to identify all the objects that could ever be in the string that needs to be match. From there you can start generalizing the objects so that a pattern can be developed.
The main site that I use for regular expressions is http://regexlib.com/RETester.aspx . As far as downloadable software have a look here, I have tried and used the first three.
The Regulator
http://sourceforge.net/projects/regulator/
Expresso 3.0
http://www.ultrapico.com/Expresso.htm
Regular Expression Designer
http://www.radsoftware.com.au/regexdesigner/
Regex Tester and Debugger
http://www.regexbuddy.com/test.html
The only values to be modified are those values that are in one of the following three markers:
A) corpse_make_list={}
B) additional_make_list={}
C) additional_make_multi_list
because you had stated that, "we'll first have to notice wether its in between corpse_make_list={} or additional_make_list={} or additional_make_multi_list
In order to write a Regex expression the rules must be identified to know what exactly needs to be matched so that a pattern can be developed for that specific pattern. The the first thing that needs to be done is to identify all the objects that could ever be in the string that needs to be match. From there you can start generalizing the objects so that a pattern can be developed.
The main site that I use for regular expressions is http://regexlib.com/RETester.aspx . As far as downloadable software have a look here, I have tried and used the first three.
The Regulator
http://sourceforge.net/projects/regulator/
Expresso 3.0
http://www.ultrapico.com/Expresso.htm
Regular Expression Designer
http://www.radsoftware.com.au/regexdesigner/
Regex Tester and Debugger
http://www.regexbuddy.com/test.html
ASKER