使用LINQ根据另一个列表中的项目来过滤项目列表

3
我正在通过实践学习LINQ。这似乎是我应该能够使用它的情况,但我无法确定是否可能或者我是否在错误的方向上努力。
在下面的用例中,我能否使用一行LINQ查询实现方括号[]中的内容?
List<Command> list1, list2;

PopulateCommandLists(list1, list2);

foreach(Command cmd in list1)
{
    if ([cmd.Name is present as the Name in any of list2's Command objects])
    {
        //some code.
    }
}

哇,这个问题有很多好的答案。:) 谢谢大家! - John Humphreys
5个回答

6

试试这个:

if (list2.Any(item => item.Name == cmd.Name)) {
}

以下是语句的"解剖":

  • Any将其条件应用于list2的每个项目,并在从列表中返回任何项目的true时返回true
  • Any内部的谓词测试item的名称是否等于cmd的名称。

您也可以将 if 折叠为LINQ:

foreach (var cmd in list1.Where(c => list2.Any(item => item.Name == c.Name))) {
    ...
}

在你的最后一段代码中,由于已经有一个名称为 cmdforeach 变量,所以在 Where 调用中你不能使用 cmd 作为 lambda 变量名。 - Jeppe Stig Nielsen
实际上,抱歉,我错了!我刚刚测试了一下。看起来 cmdin 关键字之后不在作用域内,所以你的示例在你编辑之前是有效的。抱歉,我太着急了。 - Jeppe Stig Nielsen
1
@JeppeStigNielsen 没问题,修改后的代码更易读,因为它消除了每个变量意义的歧义,即使读者(包括我自己)对作用域规则不是100%确定。 - Sergey Kalinichenko

5
if (list2.Any(x => x.Name == cmd.Name)) { }

5
我认为这是您想要的内容。
if (list2.Any(l2c => l2c.Name == cmd.Name))
{ ... }

但是你可以将它添加到foreach中,避免在代码中使用if

foreach(Command cmd in list1.Where(l1c => list2.Any(l2c => l2c.Name == l1c.Name)))
{
    ... some code ...
}

如果您控制Command类并可以在其中定义相等性(覆盖Equals等),您可以直接使用Intersect
foreach(var cmd in list1.Intersect(list2))
{ ... }

如果您无法控制Command或不想在类中定义相等性,仍然可以使用带有IEqualityComparerIntersect

foreach(var cmd in list1.Intersect(list2, new CommandComparer()))
{ ... }

class CommandComparer : IEqualityComparer<Command>
{ ... }

3
我认为您正在寻找类似于这样的东西。
if(list2.Any(list2cmd=> list2cmd.Name == cmd.name))
{
    // do stuff
}

3

你可以获取可枚举对象本身,如下所示:

var query = list1.Where(cmd => (list2.Any(item => item.Name == cmd.Name)));

然后只需要循环遍历query,它将包含您想要的每个Command

foreach( Command cmd in query)
{
    // Do something
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接