开发者

Grouping KeyValue pairs to Dictionary

开发者 https://www.devze.com 2023-01-21 02:54 出处:网络
I have the following code : using System.Collect开发者_开发问答ions.Generic; public class Test { static void Main()

I have the following code :

using System.Collect开发者_开发问答ions.Generic;


public class Test
{
    static void Main()
    {

        var items = new List<KeyValuePair<int, User>>
                        {
                            new KeyValuePair<int, User>(1, new User {FirstName = "Name1"}),
                            new KeyValuePair<int, User>(1, new User {FirstName = "Name2"}),
                            new KeyValuePair<int, User>(2, new User {FirstName = "Name3"}),
                            new KeyValuePair<int, User>(2, new User {FirstName = "Name4"})
                        };

    }
}
public class User
{
    public string FirstName { get; set; }
}

Above as you can see there are multiple users for same key . Now I want to group them and convert the list object to dictionary in which the Key will be the same(1,2 as shown above) but the value will be the collection.Like this:

 var outputNeed = new Dictionary<int, Collection<User>>();
        //Output:
        //1,Collection<User>
        //2,Collection<User>

i.e they are grouped now.

How can I achieve that ?


I would suggest you use a Lookup<TKey, TElement> instead. This data-structure is specifically intended for use as a map from keys to collections of values.

//uses Enumerable.ToLookup: the Id is the key, and the User object the value
var outputNeeded = items.ToLookup(kvp => kvp.Key, kvp => kvp.Value);

Of course, if you do need the dictionary (to allow for mutability perhaps), you can do something like:

var outputNeeded = new Dictionary<int, Collection<User>>();

foreach(var kvp in list)
{
   Collection<User> userBucketForId;

   if(!outputNeeded.TryGetValue(kvp.Key, out userBucketForId)) 
   {
       // bucket doesn't exist, create a new bucket for the Id, containing the user
       outputNeeded.Add(kvp.Key, new Collection<User> { kvp.Value });
   }
   else 
   {   // bucket already exists, append user to it.
       userBucketForId.Add(kvp.Value);
   }
}

On another note, theCollection<T>class is not all that useful unless you intend to subclass it. Are you sure you don't just need aList<User>?


Here's an example using LINQ's ToDictionary:

var output = items.GroupBy(kvp => kvp.Key)
                  .ToDictionary(group => group.Key,
                                group => group.Select(kvp => kvp.Value).ToList());

It results in a Dictionary<int,List<User>>.


Given your initial variable "item", and the suggested output variable "outputNeed", this is what you need to do:

NOTE:This is not actual c#/vb code, so please change this pseudo as required (I don't have a VS Studio at hand at the moment):

foreach (KeyValuePair<int, User> pair in items) 
{
    //add a new collection if this is the first time you encounter the key
    if (! outputNeed.Contains(pair.Key) 
    {
        outputNeed[pair.Key] = new ArrayList<User>());
    }
    //add the user to the matching collection
    outputNeed.Add(pair.Key, pair.User);
}

Good luck


foreach (var u in items)
{
    if (outputNeed.Contains(u.Key)) {
        outputNeed[u.Key].Add(u.Value);
    }
    else {
        Collection<User> a=new Collection<User>();
        a.Add(u.Value);
        outputNeed.Add(u.Key,a);
    }
}


Here is my solution :

var items = new List<KeyValuePair<int, User>>
{
    new KeyValuePair<int, User>(1, new User { FirstName = "Name1" }),
    new KeyValuePair<int, User>(1, new User { FirstName = "Name2" }),
    new KeyValuePair<int, User>(2, new User { FirstName = "Name3" }),
    new KeyValuePair<int, User>(2, new User { FirstName = "Name4" })
};

var result = (
    from item in items
    group item.Value by item.Key into grouped
    select grouped
).ToDictionary(g => g.Key, g => g);

DotNetFiddle

0

精彩评论

暂无评论...
验证码 换一张
取 消