如何用 LINQ 替换嵌套循环 - 以一种干净、可管理的方式

How to replace nested loops with LINQ - in a clean, manageable manner

Codewise,使用 linq 执行此操作的最简洁方法是什么?下面,我有一个粗略的例子,我想根据名称找到一个匹配的 class 实例。

class item
{
   string name {get;set;}
   int identifier {get;set;}
}

void DoSomething()
{
  List<item> List1 = GetSampleItems();
  List<item> List2 = GetOtherSampleItems();

  for(int a=0;a<List1.count;a++)
  {
     for(int b=0;b<List2.count;b++)
     {
         if(List1[a].identifier == List2[b].identifier)
         { 
            List1[a].name = List2[b].name;
         }
     }
  }
}

Linq 用于查询,而不是更新,因此您仍然需要循环遍历结果以进行更改,但是您可以 join 像这样匹配两个列表:

var query = from l1 in List1
            join l2 in List2
                on l1.identifier equals l2.identifier 
            select new {l1, l2};

现在循环查询以更新 l1 项:

foreach(var item in query)
    item.l1.name = item.l2.name;

附带说明一下,您的操作方式没有任何错误(除了如果找到匹配项,您可以跳出内部循环)。如果您了解它的工作原理并且性能可以接受,则没有令人信服的理由来更改它。

这应该有效:

var query = from l1 in List1
            join l2 in List2 on l1.identifier equals l2.identifier
            select new 
            {
                l1values = l1,
                l2Name = l2.name
            };

foreach(var item in query)
    item.l1Values.name = item.l2Name;

更好的方法是使用 Dictionary<TK,TV>:

Dictionary<int,item> l2dic = List2.ToDictionary(x => x.identifier);
item itm;
List1.ForEach(x => {
    if(l2dic.TryGetValue(x.identifier,out itm)) {
        x.name = itm.name;
    }
});

或者如@Rawling 所说,使用 foreach 循环代替:

Dictionary<int,item> l2dic = List2.ToDictionary(x => x.identifier);
item itm;
foreach(item x in List1) {
    if(l2dic.TryGetValue(x.identifier,out itm)) {
        x.name = itm.name;
    }
}

Ideone demo(对您的 item class 稍作修改)。

这平均以线性时间运行,而您的方法以二次时间运行。

然而,假设 标识符是唯一的:同一列表中的两个元素不能具有相同的标识符。

结论是变量通常以小写字母开头,因此 list1list2 而 classes 和属性以大写字母开头(这个 Item, IdentifierName).