【问题标题】:C# / .NET comparing two large lists and finding missing items from both listC# / .NET 比较两个大列表并从两个列表中查找缺失的项目
【发布时间】:2019-08-04 04:34:34
【问题描述】:

所以基本上我有两个大列表,如下所示:

public class Items
{
 public string ItemID { get; set; }
}


var oldList = new List<Items>(); // oldList

var newList = new List<Items>(); // new list

两个列表都非常大,如果它们都很大(超过 30 秒),由于执行时间很短,因此简单的双 foreach 是不够的。

在我在 stackoverflow 上提出的上一个问题中,我得到了关于如何比较这两个相同列表并找出哪些项目具有不同 QuantitySold 参数的回复,然后将其存储在名为“DifferentQuantityItems”的第三个列表中,如下所示:

var differentQuantityItems =
    (from newItem in newList
     join oldItem in oldList on newItem.ItemID equals oldItem.ItemID
     where newItem.QuantitySold != oldItem.QuantitySold
     select newItem).ToList();

现在我想从这两个列表中得到以下信息:

- A list of items that are present in newList, but not in oldList

- A list of items that are present in oldList, but not in newList

我怎样才能做到这一点?有人可以帮帮我吗?

附:我会“知道”其中一个列表中缺少任一项目的方式是通过属性“ItemID”...

【问题讨论】:

  • 有人吗? =)
  • 你可以试试intersectionunionLINQdocs.microsoft.com/en-us/dotnet/api/…
  • 您可以将Equals 方法与自定义比较器类一起使用
  • 使用LINQ不会保证任何性能提升,看看这里stackoverflow.com/questions/11124797/…
  • @Aarif 哦,当我看到其中一个回复中提到的并行循环时,我立即跑掉了......我对并行循环有不好的经历哈哈 =D

标签: c# linq


【解决方案1】:

已编辑

Except 会运行得更快。 Here你可以读到它的性能

var missedOld = oldList.Except(newList, new ItemsEqualityComparer());
var oldList= oldList.Except(missedOld, new ItemsEqualityComparer());

旧答案

缺少项目的两个不同列表

var missedOld = oldList.Where(x => !newList.Select(i => i.ItemID).Contains(x.ItemID)) 
var missedNew = newList.Where(x => !oldList.Select(i => i.ItemID).Contains(x.ItemID))

一个列表中的所有错过的项目:

oldList.Concat(newList).GroupBy(x => x.ItemID).Where(x => x.Count() < 2).Select(x => x.Value).ToList()

【讨论】:

  • 您不应该创建一个新变量并将新值存储在其中吗?
  • P.S.我想将两个列表中缺少的项目分隔在两个不同的列表中... =d
  • @User987 是的,当然你应该把这个表达式的值放到新变量中并使用它而不是
  • 这是否会从旧列表或新列表中获取缺少的项目? :D
  • @User987 你也可以通过类似的属性进行比较:var missedOld = oldList.Where(x =&gt; !newList.Select(l =&gt; l.ItemID).Contains(x.ItemID))
【解决方案2】:

您是否考虑过将列表转换为哈希集并使用 except 方法?

Difference between two lists

还有:Is there a way to get the difference between two sets of objects in c#

【讨论】:

  • 看起来不错,如果可能的话,你能给我举个例子吗? :)
  • 同意尝试Except(),因为内部使用HashSet应该是O(1)或者O(log N)复杂度(虽然我不是100%,但是在测试中好像所以)
【解决方案3】:
var items = new List<int>(oldList.Select(x => x.ItemID ));
var missingValues = newList.Where(x => !diffids.Contains(x.ItemID)).ToList();

你也可以使用except。

【讨论】:

  • 嗯,这个让我有点困惑...我可以提取类形式的项目吗?不仅仅是整数值..:D
【解决方案4】:

如果列表足够大以至于嵌套循环需要 30 秒,我建议您将每个列表的项目放入相应的 HashSet 并使用它来查找异常。哈希表将以 O(1) 或 O(log N) 缩放,而比较 2 个未排序的列表是 O(n^2)。

也就是说,尝试使用 Linq except()

var notinNewList = oldList.Except(newList);

如果我没记错的话,.Except() 的内部实现依赖于 HashSets

其次,如果列表已排序,或者可以预先排序,那么您可以在没有嵌套循环的情况下一次性完成线性传递,这可能比任何方法都快。

我不建议使用 List.Contains(),因为它是一个线性实现,这将导致您试图避免的 O(n^2),尽管由于 Linq 语法,它看起来更漂亮糖。

【讨论】:

    【解决方案5】:
    var items = newList.Where(n => !oldlist.Any(o => o.ItemID == n.ItemID)).ToList();
    

    它更加敏捷,因为您不需要再次去 DB 并且不使用像 SQL 中的 like 一样的 Contains 并且它也在一行中。..

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-09-27
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多