如何使用 LINQ 或 Lambda 代替嵌套和多个 foreach 语句

How to use LINQ or Lambda instead of nested and multiple foreach statements

如何使用 LINQ 或 Lambda 代替嵌套和多个 foreach 语句。

我想使用比嵌套 foreach 语句更好的语法来用第二个列表中的项目覆盖初始列表。

在下面的代码中:

您的嵌套循环用 join 表示最有效。此外,在效率方面,不必对整个列表进行线性搜索只是为了删除一个元素然后添加一个新元素,这将有助于提高效率。我们可以使用 Enumerable.Select() 的重载在结果中嵌入项目索引,以便可以直接替换元素。

把它们放在一起,看起来像这样:

var join = from p1 in initialList.Select((p, i) => new { Person = p, Index = i })
           join p2 in secondList on p1.Person.Value equals p2.Value
           select new { Index = p1.Index, Replacement = p2 };

foreach (var item in join.ToList())
{
    initialList[item.Index] = item.Replacement;
}

以上代码替换了以 personsToRemovepersonsToUpdate 列表的声明开始的原始代码,以及前三个 foreach 循环(即除了显示最终结果)。

备注:

  • 代码从 initialList 合成一个匿名类型,其中包含 Person 实例和该实例在列表中的索引。
  • join 子句将 Value 属性相等的每个列表中的所有项目配对。

重要提示: 如果任一列表中有多个元素具有相同的 Value 属性,则它们各自与另一个列表中的所有其他元素配对具有相同 Value 的列表。 IE。如果 initialList 有两个元素具有 "foo" 的 Value,而 secondList 有三个这样的元素,那么您将得到 六个 元素在生成的连接中。您的问题没有定义这是否可能,也没有定义您希望发生什么,所以我在这里忽略了这种可能性。 :)

  • join 结果被投影到一个新的匿名类型,其中包含要替换的元素的索引和新值。
  • 查询结果通过调用ToList()具体化。这是必要的,因为否则会延迟连接并且修改 initialList 会使查询无效。
  • 当然,在剩下的 foreach 中,代码接下来需要做的就是将查询确定的替换值分配给列表中适当的索引位置。

您也可以使用泛型。以下是适合您的短代码:

    initialList.ForEach(p =>
    {
        if (secondList.Any(sp => sp.Value == p.Value))
        {
            initialList.Remove(p);
            initialList.Add(secondList.Single(spu => spu.Value == p.Value));
        };
    });