【问题标题】:Return an anonymous list from a List of dictionaries<string, string> where the key equals a value从字典列表中返回一个匿名列表<字符串,字符串>,其中键等于一个值
【发布时间】:2019-06-13 14:43:25
【问题描述】:

我有一个名为dataList&lt;Dictionary&lt;string, string&gt;&gt;。我想使用 LINQ 返回 3 个值,其中键等于一个术语。

List<Dictionary<string, string>> data = new List<Dictionary<string, string>>
    {
        new Dictionary<string, string>
        {
            { "INDGEN", "100"},
            { "NO", "101"},
            { "DATE", "JUN"},
            { "PRD", "1"}
        },
        new Dictionary<string, string>
        {
            { "INDGEN", "200"},
            { "NO", "101"},
            { "DATE", "JULY"},
            { "PRD", "2"}
        },
        new Dictionary<string, string>
        {
            { "INDGEN", "300"},
            { "NO", "101"},
            { "DATE", "AUG"},
            { "PRD", "3"}
        },
        new Dictionary<string, string>
        {
            { "NO", "400"},
            { "INDGEN", "101"},
            { "DATE", "SEP"},
            { "PRD", "4"}
        },
        new Dictionary<string, string>
        {
            { "INDGEN", "500"},
            { "NO", "101"},
            { "DATE", "OCT"},
            { "PRD", "5"}
        },
        new Dictionary<string, string>
        {
            { "NO", "600"},
            { "INDGEN", "101"},
            { "DATE", "NOV"},
            { "PRD", "6"}
        }
    };

上面是一个示例列表。我希望能够返回 "INDGEN""DATE""PRD"

当前实现:

data.SelectMany(x => x.Where(y => y.Key == "INDGEN" || 
             y.Key == "DATE" || y.Key == "PRD" )).Select(z => z.Value);

目前的结果:

100
JUN
1 
200
AUG
2
300
SEP
3
101
OCT
4
500
NOV
5
101
DEC
6   

以上内容返回正确的项目,但没有将它们分组到匿名集合中。如何扩展上述内容以获得如下所示的预期结果?

期望的结果:

{"JUN", "100", "1"},
{"JULY", "200", "2"},
{"AUG", "300", "3"},
{"SEP", "400", "4"},
{"OCT", "500", "5"},
{"NOV", "600", "6"}

【问题讨论】:

  • 解决这个问题的方法是对一个single字典求解,并首先产生一个single记录。假设您有一本字典,而不是字典列表,并且您想要生成一个这样的记录。你能解决那个场景的问题吗?你能告诉我们解决这个问题的代码吗?通过编写一个方法来做到这一点,ExtractRecord,比如说,它解决了更简单的问题。那么更复杂的问题就容易解决了;它是data.Select(ExtractRecord).ToList()
  • 假设我们保证每个字典都能够产生记录;在你的场景中是这样吗?
  • 字典集总让我觉得“huuuugh???!!!”通常它们服务于特定目的并具有一定数量的属性,这使它们成为一个类的良好候选者。更好地理解和维护 - 特别是当您的对象变得更加复杂时。
  • @EricLippert 字典将始终生成带有值的记录。

标签: c# linq dictionary


【解决方案1】:

您可以尝试从每个字典中记录:

List<Dictionary<string, string>> data = ...

var result = data
  .Select(dict => 
     new {
       date = dict.TryGetValue("DATE", out var dateVal) ? dateVal : null,
       indGen = dict.TryGetValue("INDGEN", out var indGenVal) ? indGenVal : null,
       prd = dict.TryGetValue("PRD", out var prdVal) ? prdVal : null
   })
   // If we want to remove incomplete records
  .Where(item => item.date != null && item.indGen != null && item.prd != null);

【讨论】:

  • 这是一个很好的解决方案;如果我写它,我会创建一个辅助方法V GetValueOrDefault&lt;K, V&gt;(this Dict&lt;K, V&gt; d, K k) =&gt; d.TryGetValue(k, out var v) ? v : default(V); 现在你的投影更清晰:date = dict.GetValueOrDefault("DATE"), …
【解决方案2】:

您可以尝试以下方法。请记住,您可以更改默认值

var anonCollection = data.Where(d => d.GetValueOrDefault("DATE", null) != null && d.GetValueOrDefault("INDGEN", null) != null && d.GetValueOrDefault("PRD", null) != null)
            .Select(d => new []{ d.GetValueOrDefault("INDGEN", null), d.GetValueOrDefault("DATE", null), d.GetValueOrDefault("PRD", null) }).ToList();

【讨论】:

  • 如果Where 中的谓词为真,那么Select 中的投影将永远不会有默认值,因此无需调用GetValueOrDefaultSelect 可能只是 ...{d["INDGEN"], d["DATE"], d["PRD"]}
  • 如果键不存在,则 Where 中的谓词为 false,这样可以防止索引器崩溃,因为它从不运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多