用于多级嵌套集合上的等效 for 循环的 LINQ,提取索引信息

LINQ for equivalent for-loop on multi-level nested collection, extracting index information

提问人:Happy Green Kid Naps 提问时间:12/30/2021 最后编辑:Happy Green Kid Naps 更新时间:12/30/2021 访问量:432

问:

我有一个实例变量是这样声明的 -_foo

List< Dictionary<int, HashSet<int> > > _foo;

是的,它是一个凌乱的数据结构,它是一个字典列表,其键是一个整数,其关联值是整数的 HashSet。

我想知道是否可以编写一个LINQ表达式来执行与此代码片段等效的操作:

var myList = new List<(int, int, int)>();
for (int xx = 0; xx < _foo.Count; ++xx)
    foreach (var zzyy in _foo[xx])
        if (zzyy.Value.Count == 1)
            myList.Add((xx, zzyy.Value.First, zzyy.Key));

换句话说,我想捕获 List 中 Dictionary 值 (HashSet) 仅包含单个值的元素的索引。与此索引一起,我还捕获了 Dictionary-Key 和 Dictionary-value 中相应的唯一值。

C# LINQ 嵌套列表 LINQ 到对象

评论

2赞 Doc Brown 12/30/2021
由于您想获取索引,因此我不会期望 Linq 解决方案比您当前的解决方案更短或更具可读性。xx

答:

2赞 dbso 12/30/2021 #1

foreach 可以写成

myList.AddRange(_foo[xx]
  .Where(zzyy => zzyy.Value.Count == 1)
  .Select(zzyy => (xx, zzyy.Value.First(), zzyy.Key)));
1赞 Caius Jard 12/30/2021 #2

在我看来,作为 Linq 的整个事情将是

var myList = _foo.SelectMany((d,x) =>
  d.Where(kvp => kvp.Value.Count==1)
    .SelectMany(
      kvp => kvp.Value,
      (kvp, hsv) => (x,kvp.Key,hsv)
    )
).ToList();

..但老实说,我不确定它是否比你所拥有的更清晰或更高性能。

考虑到你有你写的东西,它有效,易于理解和调试。然而,必须寻求外部帮助才能将其转换为更难理解的形式,这意味着如果需要,调试将变得更加困难

我确实认为使用部分 LINQ 可能会有所帮助:

var myList = new List<(int, int, int)>();
for (int fi = 0; fi < _foo.Count; ++fi)
    foreach (var kvp in _foo[fi].Where(kvp => kvp.Value.Count == 1))
        myList.Add((fi, kvp.Value.First(), kvp.Key));

..但随后就更啰嗦了。你可以看到另一个答案,它试图用更长、更复杂的东西替换 foreach

我不会理会它,把它归结为“LINQ 是一把锤子,但不是每个问题都是钉子”的情况之一。也许花点时间看看你是否可以减少这个复杂的嵌套“哈希集词典列表”数据结构,你已经进入了更容易使用😀的东西