I have the following string:
string x = "23;32;323;34;45";
and I want to replace 23 with X as below:
x = "x:32;323;34;45";
but when I try it, I get this instead:
x = "x:32;3x;34;45";
Is there a way I can get the expecte output?
You will need a regular expression (regexp). The replacement rule here is
word boundary
23
word boundary
so your code would look like this
var result = Regex.Replace(input, #"\b23\b", "X");
An alternative approach would be to split your string, replace matching elements and join to new string>
var result = string.Join(";", input.Split(";").Select(v => v == "23" ? "X" : v));
Update: Update value in Dictionary
Assuming you know the key, that's easy:
myDict["thekey"] = Regex.Replace(myDict["thekey"], #"\b23\b", "X");
If you want to do this replacement for all items, I'd do it like this, but I'm not sure, if this is the best possible solution:
[Fact]
public void Replace_value_in_dict()
{
// given
var mydict = new Dictionary<string, string>
{
{ "key1", "donothing" },
{ "key2", "23;32;323;34;45" },
};
// when
var result = mydict
.Select(kv => (kv.Key, Regex.Replace(kv.Value, #"\b23\b", "X")))
.ToDictionary(x => x.Item1, x => x.Item2);
// then
Assert.Equal(result, new Dictionary<string, string>
{
{ "key1", "donothing" },
{ "key2", "X;32;323;34;45" },
});
}
You should use regex
var x="23;32;323;34;45";
var res = Regex.Replace(x, #"\b23\b", "x");
Console.WriteLine(res);
Working sample
Related
Have a Dictionary <string,string> as follows.
var d = new Dictionary<string, string>
{
{ "d.b.f", "x1" },
{ "d.z.x.f", "x2" },
{ "d.y.f.x.f", "x3" }
};
Want to construct a new Dictionary with first (d) & last (f) excluded from each key in dictionary. So result looks
var res = new Dictionary<string, string>
{
{ "b", "x1" },
{ "z.x", "x2" },
{ "y.f.x", "x3" }
};
I tried as follows.
var abc = d.Select(x => Helper(x));
private static KeyValuePair<string,string> Helper(KeyValuePair<string,string> x)
{
var array = x.Key.Split('.').ToList();
return new KeyValuePair<string, string>(string.Join(".", array.Where(z => array.IndexOf(z) != 0 && array.IndexOf(z) != array.Count - 1)), x.Value);
}
now abc has my required result. Is there an efficient way to do the same thing?
If you know that you will always have d. in front, and .f on the end, you could simply do a substring of your key.
private static KeyValuePair<string, string> Helper(KeyValuePair<string, string> x)
{
// starting index of 2, to skip "d.", and length of the key minus "d." and ".f"
var substring = x.Key.Substring(2, x.Key.Length - 4);
return new KeyValuePair<string, string>(substring, x.Value);
}
Alternatively, if you will actually have more characters in front and behind (instead of just d. and .f), you could calculate the index of the first . and last . and then create a substring from that:
private static KeyValuePair<string, string> Helper(KeyValuePair<string, string> x)
{
// d.b.f
var startIndex = x.Key.IndexOf('.') + 1; // 2
var endIndex = x.Key.LastIndexOf('.'); // 3
var length = endIndex - startIndex; // 1
var substring = x.Key.Substring(startIndex, length); // b
return new KeyValuePair<string, string>(substring, x.Value);
}
I'm just learning how to program, and therefore I didn't really understand LINQ.
I have:
Dictionary<string, Dictionary<string, string>> dirData = new Dictionary<string, Dictionary<string, string>>
{
{
"key1", new Dictionary<string, string>
{
{"subKey1", "value546" },
{"subKey2", "value412" },
{"subKey3", "value100" },
{"subKey4", "value27" }
}
},
{
"key2", new Dictionary<string, string>
{
{"subKey1", "value27" },
{"subKey2", "value98" },
{"subKey3", "value100" }
}
},
{
"key3", new Dictionary<string, string>
{
{"subKey1", "value29" },
{"subKey2", "value202" },
{"subKey3", "value22" },
{"subKey5", "value1" },
{"subKey6", "value3" }
}
}
};
I need to return the Dictionary<string, Dictionary <string, string >> where subkey == "subKey3" with the value value == "value100".
How can this be organized using LINQ?
You can use the following code snippet, there are two of them in your sample BTW:
var result = dirData.Values.Where(d => d.ContainsKey("subKey3") && d["subKey3"] == "value100");
Update
I need to return the Dictionary<string, Dictionary <string, string >>
where subkey == "subKey3" with the value value == "value100".
Get Dictionary of Dictionaries:
Dictionary<string,Dictionary<string,string>> result = dirData.Where(d => d.Value.ContainsKey("subKey3") && d.Value["subKey3"] == "value100").ToDictionary(k=>k.Key,v=>v.Value);
Something along the lines of
var vals = dirData.Where(x => x.Value.Keys.Contains("subKey1") && x.Value.Values.Contains(("value29")));
should work. I just tested it using vals.Count() and got the number 1 returning.
Also, just as a heads up: there are two missing commas in your sub-dictionaries :)
Edit: I think that the answer by #Access Denied actually is probably better. Just leaving mine as an alternative.
Just complicating it a bit, you can also use Linq-object this way
var test = from x in dirData
where x.Value.Any(m => m.Key == "subKey3" && m.Value == "value100")
select x;
Here's another way:
List<Dictionary<string, string>> result = dirData.Where(w => w.Value["subKey3"] == "value100").Select(s => s.Value).ToList();
I'm presuming that more than one of the dictionaries can match the condition based on your sample data, therefore this statement returns a list of dictionaries. If you only expect one match you should replace the ToList() with Single()/SingleOrDefault() as appropriate.
probably something like
var data = dirData.Where(d => d.Value.Any(x => x.Key == "subKey3" && x.Value == "value100")).ToList();
if you are looking for only those entries where key = "subKey3" and value = "value100" then probably use SelectMany() like
var data = dirData.SelectMany(x => x.Value).Where(x => x.Key == "subKey3" && x.Value == "value100").ToList();
I need to replace all placeholders like {text} with a corresponding value from a dictionary.
This is my code:
var args = new Dictionary<string, string> {
{"text1", "name"},
{"text2", "Franco"}
};
saveText(Regex.Replace("Hi, my {text1} is {text2}.", #"\{(\w+)\}", m => args[m.Groups[1].Value]));
The problem is: if the text in the input string does not exist in the dictionary, it throws an exception but I rather need to replace the placeholder with the string "null".
Just expand your lambda:
var args = new Dictionary<string, string> {
{"text1", "name"},
{"text2", "Franco"}
};
saveText(Regex.Replace("Hi, my {text1} is {text2}.", #"\{(\w+)\}", m => {
string value;
return args.TryGetValue(m.Groups[1].Value, out value) ? value : "null";
}));
I would use LINQ to create a single Func<string, string> that performs all of the replacements in one go.
Here's how:
var replace = new Dictionary<string, string>
{
{ "text1", "name" },
{ "text2", "Franco" }
}
.Select(kvp => (Func<string, string>)
(x => x.Replace(String.Format("{{{0}}}", kvp.Key), kvp.Value)))
.Aggregate<Func<string, string>, Func<string, string>>(
x => Regex.Replace(x, #"\{(\w+)\}", "null"),
(a, f) => x => a(f(x)));
var result = replace( "Hi, my {text1} is {text2} and {text3} and {text4}.");
// result == "Hi, my name is Franco and null and null."
I have a string like that : "content;123 contents;456 contentss;789 " etc..
I would like to split this string to get a Dictionary, but I don't know you to make it. I try to split the string but I got a List only.
The content (before semi colon) is always a unique string.
After the semi colon, I always have a number until I found the space.
the number is always an int (no float needs).
Could someone help me please ?
You can use the following LINQ expression:
"content;123 contents;456 contentss;789"
.Split(' ')
.Select(x => x.Split(';'))
.ToDictionary(x => x[0], x => int.Parse(x[1]));
string input = "content1;123 content2;456 content3;789";
var dict = Regex.Matches(input, #"(.+?);(\d+)").Cast<Match>()
.ToDictionary(m => m.Groups[1].Value, m => int.Parse(m.Groups[2].Value));
You can do something like this:
string value = "content;123 contents;456 contentss;789";
Dictionary<string, int> data = new Dictionary<string,int>();
foreach(string line in value.Split(' '))
{
string[] values = line.Split(';');
if (!data.ContainsKey(values[0]))
{
data.Add(values[0], Convert.ToInt32(values[1]));
}
}
var myList = "content1;number1 content2;number2 content3;number3";
var myDictionary = myList.Split(' ').Select(pair => pair.Split(';')).ToDictionary(splitPair => splitPair[0], splitPair => int.Parse(splitPair[1]));
static void Main(string[] args)
{
string content = "content;123 contents;456 contentss;789";
Dictionary<string, int> result = new Dictionary<string, int>();
content.Split(' ').ToList().ForEach(x =>
{
var items = x.Split(';');
result.Add(items[0], int.Parse(items[1]));
});
foreach(var item in result)
{
Console.WriteLine("{0} -> {1}" , item.Key, item.Value);
}
}
I have this string
string sx="(colorIndex=3)(font.family=Helvetica)(font.bold=1)";
and am splitting it with
string [] ss=sx.Split(new char[] { '(', ')' },
StringSplitOptions.RemoveEmptyEntries);
Instead of that, how could I split the result into a Dictionary<string,string>? The
resulting dictionary should look like:
Key Value
colorIndex 3
font.family Helvetica
font.bold 1
It can be done using LINQ ToDictionary() extension method:
string s1 = "(colorIndex=3)(font.family=Helvicta)(font.bold=1)";
string[] t = s1.Split(new[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
Dictionary<string, string> dictionary =
t.ToDictionary(s => s.Split('=')[0], s => s.Split('=')[1]);
EDIT: The same result can be achieved without splitting twice:
Dictionary<string, string> dictionary =
t.Select(item => item.Split('=')).ToDictionary(s => s[0], s => s[1]);
There may be more efficient ways, but this should work:
string sx = "(colorIndex=3)(font.family=Helvicta)(font.bold=1)";
var items = sx.Split(new[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries)
.Select(s => s.Split(new[] { '=' }));
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (var item in items)
{
dict.Add(item[0], item[1]);
}
Randal Schwartz has a rule of thumb: use split when you know what you want to throw away or regular expressions when you know what you want to keep.
You know what you want to keep:
string sx="(colorIndex=3)(font.family=Helvetica)(font.bold=1)";
Regex pattern = new Regex(#"\((?<name>.+?)=(?<value>.+?)\)");
var d = new Dictionary<string,string>();
foreach (Match m in pattern.Matches(sx))
d.Add(m.Groups["name"].Value, m.Groups["value"].Value);
With a little effort, you can do it with ToDictionary:
var d = Enumerable.ToDictionary(
Enumerable.Cast<Match>(pattern.Matches(sx)),
m => m.Groups["name"].Value,
m => m.Groups["value"].Value);
Not sure whether this looks nicer:
var d = Enumerable.Cast<Match>(pattern.Matches(sx)).
ToDictionary(m => m.Groups["name"].Value,
m => m.Groups["value"].Value);
string sx = "(colorIndex=3)(font.family=Helvetica)(font.bold=1)";
var dict = sx.Split(new[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries)
.Select(x => x.Split('='))
.ToDictionary(x => x[0], y => y[1]);
var dict = (from x in s1.Split(new[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries)
select new { s = x.Split('=') }).ToDictionary(x => x[0], x => x[1]);
Often used for http query splitting.
Usage: Dictionary<string, string> dict = stringToDictionary("userid=abc&password=xyz&retain=false");
public static Dictionary<string, string> stringToDictionary(string line, char stringSplit = '&', char keyValueSplit = '=')
{
return line.Split(new[] { stringSplit }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Split(new[] { keyValueSplit })).ToDictionary(x => x[0], y => y[1]); ;
}
You can try
string sx = "(colorIndex=3)(font.family=Helvetica)(font.bold=1)";
var keyValuePairs = sx.Split(new[] { '(', ')' }, StringSplitOptions.RemoveEmptyEntries)
.Select(v => v.Split('='))
.ToDictionary(v => v.First(), v => v.Last());
You could do this with regular expressions:
string sx = "(colorIndex=3)(font.family=Helvetica)(font.bold=1)";
Dictionary<string,string> dic = new Dictionary<string,string>();
Regex re = new Regex(#"\(([^=]+)=([^=]+)\)");
foreach(Match m in re.Matches(sx))
{
dic.Add(m.Groups[1].Value, m.Groups[2].Value);
}
// extract values, to prove correctness of function
foreach(var s in dic)
Console.WriteLine("{0}={1}", s.Key, s.Value);
I am just putting this here for reference...
For ASP.net, if you want to parse a string from the client side into a dictionary this is handy...
Create a JSON string on the client side either like this:
var args = "{'A':'1','B':'2','C':'" + varForC + "'}";
or like this:
var args = JSON.stringify(new { 'A':1, 'B':2, 'C':varForC});
or even like this:
var obj = {};
obj.A = 1;
obj.B = 2;
obj.C = varForC;
var args = JSON.stringify(obj);
pass it to the server...
then parse it on the server side like this:
JavaScriptSerializer jss = new JavaScriptSerializer();
Dictionary<String, String> dict = jss.Deserialize<Dictionary<String, String>>(args);
JavaScriptSerializer requires System.Web.Script.Serialization.