比较两个列表中的项目并用 LINQ 替换 foreach 循环

Compare items in two lists and replace foreach loop with LINQ

我有两个列表:

   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 包含另一个项目的一部分。 它有效,但我想简化算法并删除 foreachif.

您可以使用 System.Linq 摆脱内部循环。还通过使用 foreach 代替主循环的 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 默认情况下区分大小写。 您还可以将 IndexOf 方法与 StringComparison.OrdinalIgnoreCase 一起使用,如下所示:

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

最终考虑:element.Name 可能已经是字符串类型,除非您的 Item1.Name 属性 是某种有趣的类型。如果是这样,element.Name.ToString() 只需 element.Name.

即可转换

几个代码片段,用于查找匹配项并将两个对象的 ids 添加到 ConcurrentDictionary<string, string>

所以我们有:

var dict = new ConcurrentDictionary<string, string>();

第一

list1.ForEach(x =>
{
    list2.Where(y => y.Item2Name.IndexOf(x.Name, StringComparison.CurrentCultureIgnoreCase) >= 0)
    .ToList().ForEach(y => dict.TryAdd(x.ID, y.Item2Id));
});

第二

(from x in list1
    from y in list2
    where x.Name.IndexOf(y.Item2Name, StringComparison.CurrentCultureIgnoreCase) >= 0
    select (x, y)).ToList().ForEach(item => dict.TryAdd(item.x.ID, item.y.Item2Id));

旁注

  • 如果Item1.NameItem2.Item2Name属性都是string类型,那么就不需要像[=20=那样使用ToString()函数]行。

  • 如果Item1.IDItem2.Item2Id属性都是int类型,那么KeyValue的正确类型双字典是int类型。所以:

var dict = new ConcurrentDictionary<int, int>();