【问题标题】:List to Dictionary via LINQ ToDictionary(...)通过 LINQ ToDictionary(...) 列出字典
【发布时间】:2019-08-09 13:49:57
【问题描述】:

我目前在将列表转换为字典时遇到了一些困难。 该列表如下所示:

List<Assignment> list = new List<Assignment>();

public class Assignment {
    public String Id      {get;}
    public String Name    {get;}
    public String Product {get;}
    public String Content {get;}
}

由于 Id 和 Name 都多次出现在列表中,因此 Id 和 Name 形成一个复合键。 产品和内容共同代表一个条目。

Id 和 Name 的元组用于确定所有相关产品/内容组合的列表:

Tuple<string, string> // string1 = Id, string2 = Name

问题是:如何使用LINQ扩展方法ToDictionary()将列表转化为如下形式?

Dictionary<Tuple<string, string>, ICollection<Tuple<string, string>>>

结果应该是一个提供所有产品列表及其内容的字典,如下所示:

dict.TryGetValue(Tuple.Create("123", "Username"), out collection);

提前致谢:)

【问题讨论】:

  • 不,这不是家庭作业。我对 Linq 表达式本身进行了一些试验,结果朝着那个方向发展: .ToDictionary (x => Tuple.Create (x.Id, x.Name), x => new List > ()) 但是,这会导致 ArgumentException,因为它尝试多次添加键。老实说,我的 LINQ 知识还很新鲜。
  • 您确定Id 不是唯一的吗?如果不是唯一的,为什么要命名为Id
  • 不是唯一的。该用例类似于暴雪环境中的战斗标签,其中名称可能由于关联的数字而出现多次,并且共同唯一地标识用户。

标签: c# .net list linq dictionary


【解决方案1】:

您首先需要按复合键对元素进行分组。之后就可以生成字典了。

这可以按如下方式完成:

var dictionary = assignments.GroupBy(x=>new Tuple<string,string>(x.Id,x.Name))
                            .ToDictionary(
                                group => group.Key, 
                                group => group.Select(x => new Tuple<string,string>(x.Product,x.Content)).ToList());

如果您使用的是 C# >= 7.0,则可以使用 tuple literals 以避免调用元组构造函数。

【讨论】:

    【解决方案2】:

    另一个答案是使用.ToLookup() 而不是.ToDictionary()。简单地说:

    var lookup = list.ToLookup(x => (x.Id, x.Name), x => (x.Product, x.Content));
    

    然后你可以如下使用:

    var collection = lookup[("123", "Username")];
    

    或者,如果您愿意:

    var collection = lookup[(Id: "123", Name: "Username")];
    

    【讨论】:

    • 感谢您分享您的替代解决方案!尽管在我的请求中这是一个可靠的可能性,但以下处理需要具有给定特征的字典。
    【解决方案3】:

    如果你想让代码看起来更整洁,可以使用Named Tuples (C# 7.0) 推断成员名称,如下所示:

    var dict = list.GroupBy(x => (x.Id, x.Name))
                   .ToDictionary(
                       g => g.Key,
                       g => g.Select(x => (x.Product, x.Content)).ToList());
    

    然后你可以如下使用:

    dict.TryGetValue(("123", "Username"), out List<(string, string)> collection);
    

    或者,如果您愿意:

    dict.TryGetValue((Id: "123", Name: "Username"), out List<(string, string)> collection);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-06
      相关资源
      最近更新 更多