1

如果我有一类类型

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

还有一个列表,例如:

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 巧妙地做到这一点,如果可以,我将如何处理?

4

2 回答 2

1

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

首先,将您的类中的属性公开,然后使用以下代码:

Dictionary<string, List<string>> names = list
    .GroupBy(x => x.Last)
    .ToDictionary(x => x.Key, x => x.Select(y => y.First).ToList());
于 2013-05-18T19:04:33.360 回答
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"
}
于 2013-05-18T19:10:57.180 回答