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

时间:2015-01-27 16:28:31

标签: c# linq loops

Codewise,使用linq这是最干净的方法吗?下面,我有一个粗略的例子,我想找到一个基于名称的匹配类实例。

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;
         }
     }
  }
}

3 个答案:

答案 0 :(得分:10)

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;

作为旁注,你正在做的事情没有错误的(除非你找到匹配,否则你可以突破内循环)。如果您了解它是如何工作的并且性能是可以接受的,那么就没有令人信服的理由来改变它。

答案 1 :(得分:4)

这应该有效:

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;

答案 2 :(得分:4)

更好的方法是使用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课程。)

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

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

结论是,变量通常以小写字符开头,因此list1list2,而类和属性以大写字母开头(ItemIdentifierName)。