使用 LINQ 反转和展平字典

Posted

技术标签:

【中文标题】使用 LINQ 反转和展平字典【英文标题】:Invert and flatten a dictionary using LINQ 【发布时间】:2021-03-13 05:33:51 【问题描述】:

我有一些看起来像:


  "Item1": ["1a", "1b", "1c"],
  "Item2": ["2a"],
  "Item3": ["3a", "3b"]

我想要的是这个:


  
  "1a": "Item1", 
  "1b": "Item1", 
  "1c": "Item1",
  "2a": "Item2",
  "3a": "Item3", 
  "3b": "Item3"

我已经能够做到这一点,但只是想知道是否有更简洁的 LINQ 方式?

Dictionary<string, string[]> items = new Dictionary<string, string[]>(...);
Dictionary<string, string> endResult = new Dictionary<string, string>(); // This is correct

var reversed = items.ToDictionary(x => x.Value, x => x.Key);

foreach (var item in reversed)

    foreach (var inner in item.Key)
    
        endResult.Add(inner, item.Value);
    

【问题讨论】:

更简洁并不一定意味着更好。 ToDictionary 似乎没有必要。只需foreach 超过items 我会去 foreach。它更容易阅读。至少相同的性能。更容易调试。它实际上是 3 行代码。 foreach 中的变量名更清晰,从迭代到插入都一致。 【参考方案1】:
Dictionary<string, string> endResult = items.Select(o => o.Value.Select(v => new  Value = v, Key = o.Key ))
                                            .SelectMany(o => o)
                                            .ToDictionary(o => o.Value, o => o.Key);

【讨论】:

你不能使用.SelectMany(o =&gt; ...).ToDictionary而不是.Select(o =&gt; ...).SelectMany(o =&gt; o).ToDictionary吗?【参考方案2】:

利用Dictionary&lt;TKey, TValue&gt; 有一个接受IEnumerable&lt;KeyValuePair&lt;TKey, TValue&gt;&gt; 的构造函数这一事实添加一个更简洁的方法:

Dictionary<string, string> result = new(
    input.SelectMany(kvp => kvp.Value.Select(v => KeyValuePair.Create(v, kvp.Key))));

【讨论】:

以上是关于使用 LINQ 反转和展平字典的主要内容,如果未能解决你的问题,请参考以下文章

如何展平(int,dictionary)的字典?

C# Linq 将外键与内键反转为以字典为值的字典

使用 LINQ 展平列表列表以获取父/子列表

如何使用 linq 表达式展平嵌套对象

如何使用 linq 表达式展平嵌套对象

在捕获索引时使用 LINQ 展平列表