列表<info>其中Info有Last和First属性映射到Dictionary <last,list <first>&gt; </last,list <first> </info>

时间:2013-05-18 18:58:29

标签: c# linq linq-to-objects

如果我有一个类型

class Info
{
    public Info(string first, string last) { this.First = first; this.Last = last; }
    string First { get; private set; }
    string Last { get; private set; }
}

以List为例:

var list = new List<Info>();
list.Add(new Info("jon", "doe");
list.Add(new Info("jane", "doe");
list.Add(new Info("bason", "borne");
list.Add(new Info("billy", "nomates");

我想要映射到姓氏的排序列表,其中包含一个名字列表,即Dictionary<string,List<string>>,其中键是姓氏属性,列表是名字属性列表。

在上面的示例中,我想获得{ "doe" => { "jon", "jane" }, "borne" => { "jason" }, "nomates" => { "billy" } }

是否有可能与Linq巧妙地做到这一点,如果是这样,我将如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

您可以使用GroupByToDictionary来完成此操作:

首先,将您的属性设置为公共属性,然后使用以下代码:

Dictionary<string, List<string>> names = list
    .GroupBy(x => x.Last)
    .ToDictionary(x => x.Key, x => x.Select(y => y.First).ToList());

答案 1 :(得分:1)

我通常更喜欢使用ILookup<,>来获取此类数据。你可以像这样构建它:

list.ToLookup(e => e.Last, e => e.First);

虽然技术上不像你要求的那样Dictionary<string,List<string>>,但它仍然会做你可能想要做的大部分事情。

var firstNamesByLastName = list.ToLookup(e => e.Last, e => e.First);
foreach(var firstName in firstNamesByLastName["bourne"])
{
    Console.WriteLine(firstName); // outputs "jason"
}

请注意,您无法更改ILookup对象。因此,在构造之后不能添加新名称。但是你想用LINQ构建它的事实告诉我你几乎肯定不打算这样做。

另一个主要的语义差异是ILookup如果查询其中不存在的内容,将返回空集。同样,这通常是我喜欢的行为。

// if this used a dictionary, we'd get an exception.
foreach(var firstName in firstNamesByLastName["unborne"])
{
    Console.WriteLine(firstName); // outputs "jason"
}