C# Linq 2 维列表过滤器

Posted

技术标签:

【中文标题】C# Linq 2 维列表过滤器【英文标题】:C# Linq 2 Dimensional List Filter 【发布时间】:2021-10-29 00:54:09 【问题描述】:

编辑 - 感谢@Monofuse:

List<List<int>> list1,
list2,
list2_flattened = list2.SelectMany(x => x).ToList(); // 1d list

list1 = list1.Select(x => x.Where(y => !list2_flattened.Contains(y)).ToList()).ToList(); // 2d list (definitely not the most efficient function, but my list is constrained to a size of about 20)

鉴于 2 个列表:

List<List<int>> list1;
List<List<int>> list2;

您将如何过滤 List1 中的项目,以便最终得到 list2 中存在的项目?

忘了说:list1 必须保持原来的结构(即 List,所以 SelectMany 不是一个选项)

我正在寻找 linq 解决方案

谢谢!

【问题讨论】:

到目前为止你尝试过什么?你能分享你当前的代码尝试吗? 你能添加一个正负匹配的例子吗? @rkrahl 顺序重要吗? 你有2套套,“不存在”的定义是什么? List1 = 1,2,3,4,5,6List2 = 1,3,6,5,4 的预期结果是什么? 无论如何,我很高兴你得到了答案,但只知道这个问题有点残忍,变成了猜谜游戏。当您提出这样的问题时,请尝试非常具体 【参考方案1】:

如果我对您的理解正确,并且您想排除 list2 int 值来自list1,您可以输入

 var result = list1
   .Select(list => list
     .Where(item => !list2
       .SelectMany(dropList => dropList)
       .Any(drop => drop == item))
     .ToList())
   .ToList();

例如

  List<List<int>> list1 = new List<List<int>>() 
    new List<int>()  1, 2, 2, 3, 3, 4, 4,
    new List<int>()  2,,
    new List<int>()  5, 6,
  ;

  // We should remove 2, 5, 3 whenever they appear in list1
  List<List<int>> list2 = new List<List<int>>() 
    new List<int>()  2, 5,
    new List<int>()  3, 3,
  ;

  var result = list1
   .Select(list => list
     .Where(item => !list2
       .SelectMany(dropList => dropList)
       .Any(drop => drop == item))
     .ToList())
   .ToList();

  string report = string.Join(Environment.NewLine, result
    .Select(line => $"[string.Join(", ", line)]"));

  Console.Write(report);

结果:

[1, 4, 4]
[]
[6]

【讨论】:

【参考方案2】:

不确定是否要删除其中不再有任何内容的 list1 列表。也不确定您是否要检查子列表中的每个项目是否与 list2 的所有子列表匹配。

var list1 = new List<List<int>>();
var list2 = new List<List<int>>();
var flatList2 = list2.SelectMany(l2 => l2).Distinct();

var result = list1
    .Select(o => o
        .Where(inner => !flatList2.Contains(inner)))
    .Where(o => o.Any());

下面的完全一样,只是变量名不同。我认为这可能有助于人们了解更多。由于我们处理的是一个二维数组,我总是觉得把它想象成一个表格会更容易一些。

var table = new List<List<int>>();
var table2 = new List<List<int>>();
var distinctColumns = table2.SelectMany(row => row).Distinct();

var result = table
    .Select(row => row
        .Where(column => !distinctColumns.Contains(column)))
    .Where(row => row.Any());

【讨论】:

谢谢!这很棒!澄清一下-我只对过滤匹配的整数感兴趣(因此,如果 list1 中的任何项目存在于 list2 中的任何列表中->该项目将被排除)另外,将 list2 展平一次不是更好吗(在过滤项目之前),而不是为每个内部项目都这样做? "list2.SelectMany(l2 => l2)" - 这可以在上面声明为不在每次迭代中执行此操作。 我们也可以 distinct() 从平面版本中删除重复值

以上是关于C# Linq 2 维列表过滤器的主要内容,如果未能解决你的问题,请参考以下文章

枚举表达式列表以过滤集合

如何在 LINQ C# 中仅过滤 2 列分组中的最后一个值

使用 LINQ 按值过滤字典时遇到问题

使用 LINQ 过滤列表

Linq 加入查看而不具体化,直到过滤

csharp LINQ过滤器列表由另一个列表组成