tags:

views:

564

answers:

5

Let's say I have a List<NameValuePair>, where NameValuePair is a simple object that has a Name property and a Value property, both strings.

The list is populated with values like this:

name = "name1", value = "value1"
name = "name1", value = "value2"
name = "name2", value = "value3"
name = "name3", value = "value4"

Note that there are two instances of the "name1" key. There can be any number of keys (since this is a List).

I want to turn this List into a new list, which has just unique keys, and groups any values with the same key name as an array/list of that key.

So the above should become:

name = "name1", value = "value1", "value2" // value is a string array or list
name = "name2", value = "value3"
name = "name3", value = "value4"

What is the easiest way to accomplish this?

A: 

One way is with a dictionary:

http://arcanecode.com/2007/03/05/dictionaries-in-c-the-hashtable/

A HashTable can do what you need with unique keys. You will have to supply a List as the value however, since you will be storing multiple values per key.

Here's another easy example:

http://dotnetperls.com/hashtable-keys

You will need to iterate over each KeyValuePair in your list to populate the HashTable by storing the name as the key and the values as the value. Because you may have a name that points to multiple values, you will need your values in the HashTable to be Lists.

Check for the existence of the name in the HashTable, if it's not there, create a new list for that name and add the value to the list. If the key already exists, access that element in the HashTable and add the new value to the list that maps to the key.

AlbertoPL
+6  A: 

The easiest way is with a ILookup, which is essentially like a dictionary but can have more than one value for each key.

You can do something like this to create your lookup:

var lookup = list.ToLookup(pair => pair.name, 
                           pair => pair.value);

Then you could print the name/value pairs like this:

foreach (var nameGroup in lookup)
{
    var name = nameGroup.Key;
    foreach (string value in nameGroup)
        Console.WriteLine("Name: {0}, Value: {1}", name, value);
}
Meta-Knight
A: 

Maybe with a Dictionary<string,List<string>> you could do something like

for (var kv in mylistofnamed) {
   if (!dict.ContainsKey(kv.Key))
      dict[kv.Key] = new List<string>();
   dict[kv.Key].Add(kv.Value);
}
?

Amos Robinson
That worked well. Just for information, to process the dictionary after, I had to use foreach KeyValuePair:foreach (KeyValuePair<string, List<string>> kvp in dict){ Console.WriteLine("key " + dict.Key); Console.WriteLine("Value " + dict.Value);}
ObiWanKenobi
A: 

All classes that implement the IDictionary interface or the Generic IDictionary Interface enforce uniqueness checks for the Keys. You could use any of the classes, though I confess my preference for the Generic Dictionary<TKey, TValue> class.

When adding values, you can just check if the Dictionary object already contains the supplied Key. If not, then you can add the item into the Dictionary.

Cerebrus
+1  A: 

If you only need a read-only collection then Lookup will do the trick, as in Meta-Knight's answer.

If you need to modify the collection after its initial creation/population, then you probably need something like Dictionary<string, List<string>>. You can create and populate such a dictionary from your original list using LINQ:

var dict = list
    .GroupBy(x => x.Name)
    .ToDictionary(x => x.Key, y => y.Select(z => z.Value).ToList());
LukeH