所以基本上我有两个大列表,如下所示:
public class Items
{
public string ItemID { get; set; }
}
var oldList = new List<Items>(); // oldList
var newList = new List<Items>(); // new list
两个列表都非常大,并且如果两个列表都很大(超过30秒),则由于执行时间较差,因此简单的double 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
我该如何实现?有人可以帮我吗?
P.S。我会通过属性“ ItemID”“知道”列表中的任何一项都不存在的方式……
答案 0 :(得分:2)
您是否考虑过将列表转换为哈希集并使用Except方法?
请参见Difference between two lists
并且:Is there a way to get the difference between two sets of objects in c#
答案 1 :(得分:1)
var items = new List<int>(oldList.Select(x => x.ItemID ));
var missingValues = newList.Where(x => !diffids.Contains(x.ItemID)).ToList();
您还可以使用除外。
答案 2 :(得分:1)
已编辑
除了可以更快地工作。 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()
答案 3 :(得分:0)
如果列表足够大,以至于嵌套循环需要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语法的原因,它看起来更漂亮糖。
答案 4 :(得分:-1)
var items = newList.Where(n => !oldlist.Any(o => o.ItemID == n.ItemID)).ToList();
它更加灵活,因为您无需再次进入DB且无需使用Contains(就像在SQL中一样,它也位于一行中。)