Grouping KeyValue pairs to Dictionary
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
精彩评论