C#通过特定属性比较两个大型项目列表

Use*_*987 2 c# linq performance list c#-4.0

我有两个大的条目列表,它们的类如下所示(两个列表的类型相同):

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


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

var newList = new List<Items>(); // new list
Run Code Online (Sandbox Code Playgroud)

旧列表包含来自数据库的项目,新列表代表从API获取的项目;

两个列表都可能非常大,每个列表中包含10000+个项目(共20000个)

我需要将newList中的项目与“ oldList”中的项目进行比较,看看哪些项目具有相同的itemID值,具有不同的“ QuantitySold”值,哪些具有不同的“ QuantitySold”值应存储在名为“ differentQuantityItems”。

我可以简单地做一遍foreach列表并比较值,但是由于两个列表都很大,因此使用double foreach循环的性能非常糟糕,我做不到...

有人可以帮我这个忙吗?

@YamamotoTetsua我已经在使用IEqualityComparer来获得期望的结果,但是它没有提供我期望的结果。这就是为什么...我有第一个IEqualityComparer,看起来像这样:

 public class MissingItemComparer : IEqualityComparer<SearchedUserItems>
    {
        public static readonly IEqualityComparer<SearchedUserItems> Instance = new MissingItemComparer();

        public bool Equals(SearchedUserItems x, SearchedUserItems y)
        {
            return x.ItemID == y.ItemID;
        }

        public int GetHashCode(SearchedUserItems x)
        {
            return x.ItemID.GetHashCode();
        }
    }
Run Code Online (Sandbox Code Playgroud)

基本上,此IEqualityComparer的用法为我提供了来自newList的项目,这些项目在数据库中不存在,如下所示:

var missingItems= newItems.Except(competitor.SearchedUserItems.ToList(), MissingItemComparer.Instance).ToList();
Run Code Online (Sandbox Code Playgroud)

现在,在此列表中,我将获得来自API的新项目但不在数据库中的项目列表...

第二个IEqualityComparer基于旧列表和新列表中不同的QuantitySold:

public class ItemsComparer : IEqualityComparer<SearchedUserItems>
    {
        public static readonly IEqualityComparer<SearchedUserItems> Instance = new ItemsComparer();
        public bool Equals(SearchedUserItems x, SearchedUserItems y)
        {
            return (x.QuantitySold == y.QuantitySold);
        }
        public int GetHashCode(SearchedUserItems x)
        {
            return x.ItemID.GetHashCode();
        }
    }
Run Code Online (Sandbox Code Playgroud)

用法示例:

var differentQuantityItems = newItems.Except(competitor.SearchedUserItems.ToList(), ItemsComparer.Instance).ToList();
Run Code Online (Sandbox Code Playgroud)

这两个相等比较器的问题在于,例如第一个比较器将返回缺少的这些itemID:

123124124

123124421

512095902
Run Code Online (Sandbox Code Playgroud)

而且它们确实从我的oldList中丢失了。但是,第二个IEQualityComparer也会将这些项目作为differentQuantity项目返回,它们确实存在,但是在oldList中不存在。因此,不应将它们包含在第二个列表中。

Iva*_*oev 6

这是LINQ Join的理想人选:

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

这将返回所有具有相应的旧项目的新项目,其中旧项目的数量不同。如果您还希望包括新项目而不包含相应的旧项目,则使用左外部联接

var differentQuantityItems =
    (from newItem in newList
     join oldItem in oldList on newItem.ItemID equals oldItem.ItemID into oldItems
     from oldItem in oldItems.DefaultIfEmpty()
     where oldItem == null || newItem.QuantitySold != oldItem.QuantitySold
     select newItem).ToList();
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,联接运算符都用于快速将具有相同ItemID的项目关联起来。然后,您可以比较QuantitySold或任何其他属性。