My ultimate goal here is to turn the following string into JSON, but I would settle for something that gets me one step closer by combining the fieldname with each of the values.
Sample Data:
Field1:abc;def;Field2:asd;fgh;
Using Regex.Replace(), I need it to at least look like this:
Field1:abc,Field1:def,Field2:asd,Field2:fgh
Ultimately, this result would be awesome if it can be done via Regex in a single call.
{"Field1":"abc","Field2":"asd"},{"Field1":"def","Field2":"fgh"}
I've tried many different variations of this pattern, but can't seem to get it right:
(?:(\w+):)*?(?:([^:;]+);)
Only one other example I could find that is doing something similar, but just enough differences that I can't quite put my finger on it.
Regex to repeat a capture across a CDL?
EDIT:
Here's my solution. I'm not going to post it as a "Solution" because I want to give credit to one that was posted by others. In the end, I took a piece from each of the posted solutions and came up with this one. Thanks to everyone who posted. I gave credit to the solution that compiled, executed fastest and had the most accurate results.
string hbi = "Field1:aaa;bbb;ccc;ddd;Field2:111;222;333;444;";
Regex re = new Regex(#"(\w+):(?:([^:;]+);)+");
MatchCollection matches = re.Matches(hbi);
SortedDictionary<string, string> dict = new SortedDictionary<string, string>();
for (int x = 0; x < matches.Count; x++)
{
Match match = matches[x];
string property = match.Groups[1].Value;
for (int i = 0; i < match.Groups[2].Captures.Count; i++)
{
string key = i.ToString() + x.ToString();
dict.Add(key, string.Format("\"{0}\":\"{1}\"", property, match.Groups[2].Captures[i].Value));
}
}
Console.WriteLine(string.Join(",", dict.Values));
Now you have two problems
I don't think regular expressions will be the best way to handle this. You should probably start by splitting on semicolons, then loop through the results looking for a value that starts with "Field1:" or "Field2:" and collect the results into a Dictionary.
Treat this as pseudo code because I have not compiled or tested it:
string[] data = input.Split(';');
dictionary<string, string> map = new dictionary<string, string>();
string currentKey = null;
foreach (string value in data)
{
// This part should change depending on how the fields are defined.
// If it's a fixed set you could have an array of fields to search,
// or you might need to use a regular expression.
if (value.IndexOf("Field1:") == 0 || value.IndexOf("Field2:"))
{
string currentKey = value.Substring(0, value.IndexOf(":"));
value = value.Substring(currentKey.Length+1);
}
map[currentKey] = value;
}
// convert map to json
I had an idea that it should be possible to do this in a shorter and more clear way. It ended up not being all that much shorter and you can question if it's more clear. At least it's another way to solve the problem.
var str = "Field1:abc;def;Field2:asd;fgh";
var rows = new List<Dictionary<string, string>>();
int index = 0;
string value;
string fieldname = "";
foreach (var s in str.Split(';'))
{
if (s.Contains(":"))
{
index = 0;
var tmp = s.Split(':');
fieldname = tmp[0];
value = tmp[1];
}
else
{
value = s;
index++;
}
if (rows.Count < (index + 1))
rows.Insert(index, new Dictionary<string, string>());
rows[index][fieldname] = value;
}
var arr = rows.Select(dict =>
String.Join("," , dict.Select(kv =>
String.Format("\"{0}\":\"{1}\"", kv.Key, kv.Value))))
.Select(r => "{" + r + "}");
var json = String.Join(",", arr );
Debug.WriteLine(json);
Outputs:
{"Field1":"abc","Field2":"asd"},{"Field1":"def","Field2":"fgh"}
I would go with RegEx as the simplest and most straightforward way to parse the strings, but I'm sorry, pal, I couldn't come up with a clever-enough replacement string to do this in one shot.
I hacked it out for fun through, and the monstrosity below accomplishes what you need, albeit hideously. :-/
Regex r = new Regex(#"(?<FieldName>\w+:)*(?:(?<Value>(?:[^:;]+);)+)");
var matches = r.Matches("Field1:abc;def;Field2:asd;fgh;moo;"); // Modified to test "uneven" data as well.
var tuples = new[] { new { FieldName = "", Value = "", Index = 0 } }.ToList(); tuples.Clear();
foreach (Match match in matches)
{
var matchGroups = match.Groups;
var fieldName = matchGroups[1].Captures[0].Value;
int index = 0;
foreach (Capture cap in matchGroups[2].Captures)
{
var tuple = new { FieldName = fieldName, Value = cap.Value, Index = index };
tuples.Add(tuple);
index++;
}
}
var maxIndex = tuples.Max(tup => tup.Index);
var jsonItemList = new List<string>();
for (int a = 0; a < maxIndex+1; a++)
{
var jsonBuilder = new StringBuilder();
jsonBuilder.Append("{");
foreach (var tuple in tuples.Where(tup => tup.Index == a))
{
jsonBuilder.Append(string.Format("\"{0}\":\"{1}\",", tuple.FieldName, tuple.Value));
}
jsonBuilder.Remove(jsonBuilder.Length - 1, 1); // trim last comma.
jsonBuilder.Append("}");
jsonItemList.Add(jsonBuilder.ToString());
}
foreach (var item in jsonItemList)
{
// Write your items to your document stream.
}
Related
I need to split a line of text
The general syntax for a delivery instruction is |||name|value||name|value||…..|||
Each delivery instruction starts and ends with 3 pipe characters - |||
A delivery instruction is a set of name/value pairs separated by a single pipe eg name|value
Each name value pair is separated by 2 pipe characters ||
Names and Values may not contain the pipe character
The value of any pair may be a blank string.
I need a regex that will help me resolve the above problem.
My latest attempt with my limited Regex skills:
string SampleData = "|||env|af245g||mail_idx|39||gen_date|2016/01/03 11:40:06||docm_name|Client Statement (01.03.2015−31.03.2015)||docm_cat_name|Client Statement||docm_type_id|9100||docm_type_name|Client Statement||addr_type_id|1||addr_type_name|Postal address||addr_street_nr|||addr_street_name|Robinson Road||addr_po_box|||addr_po_box_type|||addr_postcode|903334||addr_city|Singapore||addr_state|||addr_country_id|29955||addr_country_name|Singapore||obj_nr|10000023||bp_custr_type|Customer||access_portal|Y||access_library|Y||avsr_team_id|13056||pri_avsr_id|||pri_avsr_name|||ctact_phone|||dlv_type_id|5001||dlv_type_name|Channel to standard mail||ao_id|14387||ao_name|Corp Limited||ao_title|||ao_mob_nr|||ao_email_addr||||??";
string[] Split = Regex.Matches(SampleData, "(\|\|\|(?:\w+\|\w*\|\|)*\|)").Cast<Match>().Select(m => m.Value).ToArray();
The expected output should be as follows(based on the sample data string provided):
env|af245g
mail_idx|39
gen_date|2016/01/03 11:40:06
docm_name|Client Statement (01.03.2015−31.03.2015)
docm_cat_name|Client Statement
docm_type_id|9100
docm_type_name|Client Statement
addr_type_id|1
addr_type_name|Postal address
addr_street_nr|
addr_street_name|Robinson Road
addr_po_box|
addr_po_box_type|
addr_postcode|903334
addr_city|Singapore
addr_state|
addr_country_id|29955
addr_country_name|Singapore
obj_nr|10000023
bp_custr_type|Customer
access_portal|Y
access_library|Y
avsr_team_id|13056
pri_avsr_id|
pri_avsr_name|
ctact_phone|
dlv_type_id|5001
dlv_type_name|Channel to standard mail
ao_id|14387
ao_name|Corp Limited
ao_title|
ao_mob_nr|
ao_email_addr|
You can also do it without using Regex. Its just simple splitting.
string nameValues = "|||zeeshan|1||ali|2||ahsan|3|||";
string sub = nameValues.Substring(3, nameValues.Length - 6);
Dictionary<string, string> dic = new Dictionary<string, string>();
string[] subsub = sub.Split(new string[] {"||"}, StringSplitOptions.None);
foreach (string item in subsub)
{
string[] nameVal = item.Split('|');
dic.Add(nameVal[0], nameVal[1]);
}
foreach (var item in dic)
{
// Retrieve key and value here i.e:
// item.Key
// item.Value
}
Hope this helps.
I think you're making this more difficult than it needs to be. This regex yields the desired result:
#"[^|]+\|([^|]*)"
Assuming you're dealing with a single, well-formed delivery instruction, there's no need to match the starting and ending triple-pipes. You don't need to worry about the double-pipe separators either, because the "name" part of the "name|value" pair is always present. Just look for the first thing that looks like a name with a pipe following it, and everything up to the next pipe character is the value.
(?<=\|\|\|).*?(?=\|\|\|)
You can use this to get all the key value pairs between |||.See demo.
https://regex101.com/r/fM9lY3/59
string strRegex = #"(?<=\|\|\|).*?(?=\|\|\|)";
Regex myRegex = new Regex(strRegex, RegexOptions.Multiline);
string strTargetString = #"|||env|af245g||mail_idx|39||gen_date|2016/01/03 11:40:06||docm_name|Client Statement (01.03.2015−31.03.2015)||docm_cat_name|Client Statement||docm_type_id|9100||docm_type_name|Client Statement||addr_type_id|1||addr_type_name|Postal address||addr_street_nr|||addr_street_name|Robinson Road||addr_po_box|||addr_po_box_type|||addr_postcode|903334||addr_city|Singapore||addr_state|||addr_country_id|29955||addr_country_name|Singapore||obj_nr|10000023||bp_custr_type|Customer||access_portal|Y||access_library|Y||avsr_team_id|13056||pri_avsr_id|||pri_avsr_name|||ctact_phone|||dlv_type_id|5001||dlv_type_name|Channel to standard mail||ao_id|14387||ao_name|Corp Limited||ao_title|||ao_mob_nr|||ao_email_addr||||??";
foreach (Match myMatch in myRegex.Matches(strTargetString))
{
if (myMatch.Success)
{
// Add your code here
}
}
Here's a variation of #Syed Muhammad Zeeshan code that runs faster:
string nameValues = "|||zeeshan|1||ali|2||ahsan|3|||";
string[] nameArray = nameValues.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
Dictionary<string, string> dic = new Dictionary<string, string>();
int i = 0;
foreach (string item in nameArray)
{
if (i < nameArray.Length - 1)
dic.Add(nameArray[i], nameArray[i + 1]);
i = i + 2;
}
Interesting, I will like to try:
class Program
{
static void Main(string[] args)
{
string nameValueList = "|||zeeshan|1||ali|2||ahsan|3|||";
while (nameValueList != "|||")
{
nameValueList = nameValueList.TrimStart('|');
string nameValue = GetNameValue(ref nameValueList);
Console.WriteLine(nameValue);
}
Console.ReadLine();
}
private static string GetNameValue(ref string nameValues)
{
string retVal = string.Empty;
while(nameValues[0] != '|') // for name
{
retVal += nameValues[0];
nameValues = nameValues.Remove(0, 1);
}
retVal += nameValues[0];
nameValues = nameValues.Remove(0, 1);
while (nameValues[0] != '|') // for value
{
retVal += nameValues[0];
nameValues = nameValues.Remove(0, 1);
}
return retVal;
}
}
https://dotnetfiddle.net/WRbsRu
I have a string that I am trying to parse the values from. It is in this format "43,56,12,ddl=345".
I am trying to store the ddl value (345) in a separate variable, then the other numbers in a list.
List<int> nums = new List<int>();
int? ddlValue;
How do I go about this?
You could try parsing the string for ints, and then have special checks for any other values you want to store.
var sNums = "43,56,12,ddl=345";
List<int> nums = new List<int>();
int? ddlValue;
foreach (var t in sNums.Split(',')) {
int u;
if (int.TryParse(t, out u)) {
nums.Add(u);
} else {
ddlValue = t.Split("=")[1];
}
}
You can do:
var sNums = "43,56,12,ddl=345".Split(',');
var ddl = int.Parse(sNums.First(s => s.Contains("ddl")).Replace("ddl=", ""));
var numbers = sNums.Where(s => !s.Contains("ddl")).Select(int.Parse);
*note - this will be slightly less efficient that doing it in a single loop - but more readable IMO.
You can do something like this:
List<int> nums=new List<int>();
int intVariable = 0;
string s = "43,56,12,ddl=345";
string[] split=s.Split(',');
Regex regex = new Regex(#"^\d+$");
foreach(var element in split)
if(regex.IsMatch(element))
nums.Add(Convert.ToInt32(element));
else
{
intVariable = element.Split("=")[1];
}
I mean the simplest way is a split and replace.
string values = "43,56,12,ddl=345";
string[] values1 = values.Split(',');
foreach (var x in values1)
{
list.Add(x);
}
string myvalue = values.Split(',')[3];
myvalue = myvalue.Replace("ddl=","");
this assumes your going to be getting the same format every time. Maybe more information?
EDIT-
If you will not always have 3 numbers then the ddl= then string myvalue = values.Split(',')[3]; will not work. Theres a few easy ways around it like
string myvalue = values.Split(',')[values1.Count() - 1]
My problem is with getting values from .txt file.
I have this for example[without enter]:
damage=20 big explosion=50 rangeweapon=50.0
and I want to get these values after "=". Just to make a string[] with something like that:
damage=20
big explosion=50
rangeweapon=50.0
I got some other mechanic but i want to find universal mechanic to get all values into string[] and then just check it in switch.
Thank You.
I have try to solve your problem with regex. I found one solution that is not best solution.
May be it can help or guide you to find best solution.
Please try like this
string operation = "damage=20 big explosion=50 rangeweapon=50.0";
string[] wordText = Regex.Split(operation, #"(\=\d+\.?\d?)");
/*for split word but result array has last value that empty you will delete its*/
string[] wordValue = Regex.Split(operation, #"(\s*\D+\=)"); /*for split digit that is value of word but result array has first value that empty you will delete its*/
After that you can join or do anything you want with those array.
This should parse the string you describe, but keep in mind it isn't very robust and has no error handling.
string stringToParse = "damage=20 big explosion=50 rangeweapon=50.0";
string[] values = stringToParse.Split(' ');
Dictionary<string, double> parsedValues = new Dictionary<string, double>();
string temp = "";
foreach (var value in values)
{
if (value.Contains('='))
{
string[] keyValue = value.Split('=');
parsedValues.Add(temp + keyValue[0], Double.Parse(keyValue[1]));
temp = string.Empty;
}
else
{
temp += value + ' ';
}
}
After this, the parsedValues dictionary should have the information you're looking for.
I'm not an expert about it, but what about using a Regex ?
Not the cleanest code in the world, but will work for your situation.
string input = "damage=20 big explosion=50 rangeweapon=50.0";
string[] parts = input.Split('=');
Dictionary<string, double> dict = new Dictionary<string, double>();
for (int i = 0; i < (parts.Length - 1); i++)
{
string key = i==0?parts[i]:parts[i].Substring(parts[i].IndexOf(' '));
string value = i==parts.Length-2?parts[i+1]:parts[i + 1].Substring(0, parts[i + 1].IndexOf(' '));
dict.Add(key.Trim(), Double.Parse(value));
}
foreach (var el in dict)
{
Console.WriteLine("Key {0} contains value {1}", el.Key, el.Value);
}
Console.ReadLine();
You want to read number from text.You can save your data in text like this.
damage=20,big explosion=50,rangeweapon=50. And read from text via File.ReadAllLines().
string[] Lines;
string[] myArray;
Lines = File.ReadAllLines(your file path);
for (int i = 0; i < Lines.Length; i++)
{
myArray = Lines[i].Split(',');
}
for (int j = 0; j < myArray .Length; j++)
{
string x =myArray [j].ToString();
x = Regex.Replace(x, "[^0-9.]", "");
Console.WriteLine(x);
}
I want to replace characters in a string content in file.
Below Dictionary shows the Key as unwanted character and i need to replace with the value in the Dictionary.
Dictionary<string, string> unwantedCharacters = new Dictionary<string, string>();
unwantedCharacters["É"] = "#";
unwantedCharacters["Ä"] = "[";
unwantedCharacters["Ö"] = "\\";
unwantedCharacters["Å"] = "]";
unwantedCharacters["Ü"] = "^";
unwantedCharacters["é"] = "`";
unwantedCharacters["ä"] = "{";
unwantedCharacters["ö"] = "|";
unwantedCharacters["å"] = "}";
unwantedCharacters["ü"] = "~";
Here is the code i currently using,Feel like its taking too much execution time..
for (int index = 0; index < fileContents.Length; index++)
{
foreach (KeyValuePair<string, string> item in unwantedCharacters)
{
if (fileContents.IndexOf(item.Key) > -1)
{
fileContents = fileContents.Replace(item.Key, item.Value); // Replacing straight characters
}
}
}
ie,Looping in two levels.. Any other ways implement this..Any help will be appreciated
Since you're not modifying the length of the string, if you make unwantedCharacters a Dictionary<char, char> rather than <string, string>, you can do the following:
var charArray = fileContents.ToCharArray();
for (int i = 0; i < charArray.Length; i++)
{
char replacement;
if (unwantedCharacters.TryGetValue(charArray[i], out replacement))
charArray[i] = replacement;
}
fileContents = new string(charArray);
Performance is O(n) in releation to the length of the input string.
It seems fileContents is a string value here. You could simply call replace on the string.
foreach (KeyValuePair<string, string> item in unwantedCharacters)
{
fileContents = fileContents.Replace(item.Key, item.Value);
}
Look this answer: answer
But in this code put your characteres:
IDictionary<string,string> map = new Dictionary<string,string>()
{
{"É", = "#"},
{"Ä", = "["},
{"Ö", = "\\"},
...
};
In order to replace many characters in string, consider to use StringBuilder Class. Replacing one character in string causes in creation of entirly new string so it is highly inefficient. Try the below:
var sb = new StringBuilder(fileContents.Length);
foreach (var c in fileContents)
sb.Append(unwantedCharacters.ContainsKey(c) ? unwantedCharacters[c] : c);
fileContents = sb.ToString();
I assumed here, that your dictionary contains characters (Dictionary<char, char>). It it is a case, just comment and I will edit the solution.
I also assumed, that fileContents is a string.
You can also use LINQ instead of StringBuilder:
var fileContentsEnumerable = from c in fileContents
select unwantedCharacters.ContainsKey(c) ? unwantedCharacters[c] : c;
fileContents = new string(fileContentsEnumerable.ToArray());
You want to build a filter. You process the contents of the file, and do the substitution while you process it.
Something like this:
using(StreamReader reader = new StreamReader("filename"))
using (StreamWriter writer = new StreamWriter("outfile"))
{
char currChar = 0;
while ((currChar = reader.Read()) >= 0)
{
char outChar = unwantedCharacters.ContainsKey(currChar)
? unwantedCharacters[currChar]
: (char) currChar;
writer.Write(outChar);
}
}
You can use a memeory stream if your data is in memory, or a loop through fileContents is that's a string or char array.
This solution is O(n) where n is the length of the file, thanks to the dictionary (note that you could use a simple sparse array instead of the dictionary and you would gain quite a bit of speed).
Do not iterate through the dictionary as other suggest as each substitution is O(n) so you end up with a total time of O(n*d), d being the dictionary size, as you have to go through the file many times.
Remove the foreach and replace with a for loop from 0 to item.Count. This article will help, hopefully.
I have a string on which I need to do some replacements. I have a Dictionary<string, string> where I have search-replace pairs defined. I have created following extension methods to perform this operation:
public static string Replace(this string str, Dictionary<string, string> dict)
{
StringBuilder sb = new StringBuilder(str);
return sb.Replace(dict).ToString();
}
public static StringBuild Replace(this StringBuilder sb,
Dictionary<string, string> dict)
{
foreach (KeyValuePair<string, string> replacement in dict)
{
sb.Replace(replacement.Key, replacement.Value);
}
return sb;
}
Is there a better way of doing that?
If the data is tokenized (i.e. "Dear $name$, as of $date$ your balance is $amount$"), then a Regex can be useful:
static readonly Regex re = new Regex(#"\$(\w+)\$", RegexOptions.Compiled);
static void Main() {
string input = #"Dear $name$, as of $date$ your balance is $amount$";
var args = new Dictionary<string, string>(
StringComparer.OrdinalIgnoreCase) {
{"name", "Mr Smith"},
{"date", "05 Aug 2009"},
{"amount", "GBP200"}
};
string output = re.Replace(input, match => args[match.Groups[1].Value]);
}
However, without something like this, I expect that your Replace loop is probably about as much as you can do, without going to extreme lengths. If it isn't tokenized, perhaps profile it; is the Replace actually a problem?
Do this with Linq:
var newstr = dict.Aggregate(str, (current, value) =>
current.Replace(value.Key, value.Value));
dict is your search-replace pairs defined Dictionary object.
str is your string which you need to do some replacements with.
Seems reasonable to me, except for one thing: it's order-sensitive. For instance, take an input string of "$x $y" and a replacement dictionary of:
"$x" => "$y"
"$y" => "foo"
The results of the replacement are either "foo foo" or "$y foo" depending on which replacement is performed first.
You could control the ordering using a List<KeyValuePair<string, string>> instead. The alternative is to walk through the string making sure you don't consume the replacements in further replace operations. That's likely to be a lot harder though.
Here's a lightly re-factored version of #Marc's great answer, to make the functionality available as an extension method to Regex:
static void Main()
{
string input = #"Dear $name$, as of $date$ your balance is $amount$";
var args = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
args.Add("name", "Mr Smith");
args.Add("date", "05 Aug 2009");
args.Add("amount", "GBP200");
Regex re = new Regex(#"\$(\w+)\$", RegexOptions.Compiled);
string output = re.replaceTokens(input, args);
// spot the LinqPad user // output.Dump();
}
public static class ReplaceTokensUsingDictionary
{
public static string replaceTokens(this Regex re, string input, IDictionary<string, string> args)
{
return re.Replace(input, match => args[match.Groups[1].Value]);
}
}
when using Marc Gravell's RegEx solution, first check if a token is available using i.e. ContainsKey, this to prevent KeyNotFoundException errors :
string output = re.Replace(zpl, match => { return args.ContainsKey(match.Groups[1].Value) ? arg[match.Groups[1].Value] : match.Value; });
when using the following slightly modified sample code (1st parameter has different name):
var args = new Dictionary<string, string>(
StringComparer.OrdinalIgnoreCase)
{
{"nameWRONG", "Mr Smith"},
{"date", "05 Aug 2009"},
{"AMOUNT", "GBP200"}
};
this produces the following:
"Dear $name$, as of 05 Aug 2009 your balance is GBP200"
The correct tool for this particular task is Mustache, a simple standard logicless templating language.
There are many implementations. For this example, I'm going to use stubble:
var stubble = new StubbleBuilder().Build();
var dataHash = new Dictionary<string, Object>()
{
{"Foo","My Foo Example"},
{"Bar",5}
};
var output = stubble.Render(
"Hey, watch me replace this: {{Foo}} ... with example text. Also {{bar}} is 5"
, dataHash
);
Here you are:
public static class StringExm
{
public static String ReplaceAll(this String str, KeyValuePair<String, String>[] map)
{
if (String.IsNullOrEmpty(str))
return str;
StringBuilder result = new StringBuilder(str.Length);
StringBuilder word = new StringBuilder(str.Length);
Int32[] indices = new Int32[map.Length];
for (Int32 characterIndex = 0; characterIndex < str.Length; characterIndex++)
{
Char c = str[characterIndex];
word.Append(c);
for (var i = 0; i < map.Length; i++)
{
String old = map[i].Key;
if (word.Length - 1 != indices[i])
continue;
if (old.Length == word.Length && old[word.Length - 1] == c)
{
indices[i] = -old.Length;
continue;
}
if (old.Length > word.Length && old[word.Length - 1] == c)
{
indices[i]++;
continue;
}
indices[i] = 0;
}
Int32 length = 0, index = -1;
Boolean exists = false;
for (int i = 0; i < indices.Length; i++)
{
if (indices[i] > 0)
{
exists = true;
break;
}
if (-indices[i] > length)
{
length = -indices[i];
index = i;
}
}
if (exists)
continue;
if (index >= 0)
{
String value = map[index].Value;
word.Remove(0, length);
result.Append(value);
if (word.Length > 0)
{
characterIndex -= word.Length;
word.Length = 0;
}
}
result.Append(word);
word.Length = 0;
for (int i = 0; i < indices.Length; i++)
indices[i] = 0;
}
if (word.Length > 0)
result.Append(word);
return result.ToString();
}
}
Why not just check whether such key exists?
if exists, then remove the pair, otherwise, skip this step;
add the same key, but now with newly desired value.
// say, you have the following collection
var fields = new Dictionary<string, string>();
fields.Add("key1", "value1");
fields.Add("key2", "value2");
fields.Add("key3", "value3");
// now, you want to add a pair "key2"/"value4"
// or replace current value of "key2" with "value4"
if (fields.ContainsKey("key2"))
{
fields.Remove("key2");
}
fields.Add("key2", "value4");