如果我有一个类型
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巧妙地做到这一点,如果是这样,我将如何解决这个问题?
答案 0 :(得分:1)
您可以使用GroupBy
和ToDictionary
来完成此操作:
首先,将您的属性设置为公共属性,然后使用以下代码:
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"
}