简体   繁体   中英

replace a substring in Keys of a dictionary C#

I have a Dictionary Structure as follows

Dictionary<string, ObjectData> groups=new Dictionary<string, ObjectData>();
groups.add("NC_Test1",new ObjectData());
groups.add("NC_Test2",new ObjectData());
groups.add("Test3",new ObjectData());
groups.add("NC_Test4",new ObjectData());
groups.add("Test5",new ObjectData());
groups.add("NC_Test6",new ObjectData());

I now want to remove the NC_ from the dictionary keys. So I am looking at the result as groups:

("Test1",new ObjectData()),
("Test2",new ObjectData()),
("Test3",new ObjectData()),
("Test4",new ObjectData()),
("Test5",new ObjectData()),
("Test6",new ObjectData())

I am trying as follows but I only get the items that start with NC_ . I know thats because of the where clause. Not sure how to form the lambda expression.

groups = groups.Where(x => x.Key.StartsWith("NC_")).ToDictionary(x => x.Key.Replace("NC_", ""), y => y.Value);

Remove the where clause.

You start by selecting only the NC_ prefixed items then creating a new dictionary.

groups = groups.ToDictionary(x => x.Key.Replace("NC_", string.Empty), y => y.Value);

What about key collisions ? when you strip out the NC_ from the key. Consider if you have NC_Test1 and Test1 both in the original dictionary.

Also Lambda operators do have their uses but in your case you will just get a mysterious result with no ability to debug into the code and see which items are causing the exception. for anything non trivial I usually write verbose versions first and once they are debugged and tested then condense them to lambda operations.

The following lambda example handles the collisions by overwriting the collision key's value. Maybe you might want to ignore the collisions and store them separately.

Dictionary<string, ObjectData> groups = new Dictionary<string, ObjectData>();
groups.Add("NC_Test1", new ObjectData());
groups.Add("NC_Test2", new ObjectData());
groups.Add("Test3", new ObjectData());
groups.Add("NC_Test4", new ObjectData());
groups.Add("Test5", new ObjectData());
groups.Add("NC_Test6", new ObjectData());

Dictionary<string, ObjectData> groupsclustered = new Dictionary<string, ObjectData>();
groups.ToList().ForEach( x => {
    string newKey;
    newKey = x.Key.StartsWith(@"NC_") ? x.Key.Substring(3) : x.Key;
    if (groupsclustered.ContainsKey(newKey))
    { groupsclustered[newKey] = x.Value; } else { groupsclustered.Add(newKey, x.Value); }
} );

Remove the 'where' filter, and do a conditional replace. eg

groups = groups.ToDictionary(x => x.Key.StartsWith("NC_")? x.Key.Replace("NC_", "") : x.Key, y => y.Value);

(untested)

The Where is unnecessary as you are arbitrarily limiting your input when all you want to do is a 1-to-1 conversion. A simple ToDictionary will suffice:

groups = groups.ToDictionary(k => k.Key.Replace("NC_", ""), v => v.Value);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM