首页 > 解决方案 > 比较两个列表中的项目并用 LINQ 替换 foreach 循环

问题描述

我有两个列表:

   List<Item1> list1;
   List<Item2> list2;

我有以下代码用于比较列表中的项目:

ConcurrentDictionary<string, string> compareDictionary = new ConcurrentDictionary<string, string>();

for (int i = 0; i < lis1.Count; i++)
{
   var item1Name= list1[i].Name.ToString();
   var item1Id= list1[i].ID.ToString();

   foreach (var item in list2)
   {
      if (item1Name.Contains(item.item2Name.ToLower()))
      {
          compareDictionary.TryAdd(item1Id, item.item2Id);
      }
    }
}

如果一个项目包含另一个项目的一部分,则需要Id从第一个列表中添加Id第二个列表到 ConcurrentDictionary 。Name它有效,但我想简化算法并删除foreachand if

标签: c#linqfor-loopforeachconcurrentdictionary

解决方案


您可以使用 System.Linq 摆脱内部循环。还可以通过使用 foreach 而不是 for for 主循环来简化代码:

ConcurrentDictionary<string, string> compareDictionary = new ConcurrentDictionary<string, string>();

foreach (var element in list1)
{
   var item1Name= element.Name.ToString();
   var item1Id= element.ID.ToString();
   // If this element has already one correspondence, TryAdd will fail anyway
   if(compareDictionary.ContainsKey(item1Id)) continue; 

   var found = list2.FirstOrDefault(item => item1Name.Contains(item.item2Name.ToLower()));
   if(found != null)
   {
          compareDictionary.TryAdd(item1Id, item.item2Id);
   }
}

根据您的元素命名,您还可能需要将 item1Name 设为小写。您的代码实际上会找到这种对应关系:

Parentwithlittlechild --> LittleChild

但不是这个:

ParentWithLittleChild --> LittleChild

因为 "LittleChild" 会小写,并且 String.Contains 默认情况下区分大小写。您也可以使用IndexOfwith 方法StringComparison.OrdinalIgnoreCase,如下所示:

var found = list2.FirstOrDefault(item => item1Name.IndexOf(item.item2Name, StringComparison.OrdinalIgnoreCase) >= 0);

最后的考虑:element.Name可能已经是字符串类型,除非你的Item1.Name属性是一些有趣的类型。如果element.Name.ToString()是这样,则可转换为element.Name.


推荐阅读