【问题标题】:How can I compare two generic collections [duplicate]如何比较两个通用集合[重复]
【发布时间】:2016-03-03 20:53:48
【问题描述】:

我有两个名为barcodesSource 和barcodesTarget 的通用集合。他们都是同类型的Helper。我想根据属性 BARCODE 将名为barcodesSource 的集合与第二个集合进行比较,并仅返回第一个集合中的数据,而第二个集合中没有对应的 BARCODE。

谁能告诉我解决办法?

class Helper
{
    public long BARCODE { get; set; }
    public int ITEM { get; set; }
}


List<Helper> barcodesSource = new List<Helper>();
List<Helper> barcodesTarget = new List<Helper>();

var distinctBarcodes = barcodesSource.Where(a => barcodesTarget.All(b => b.BARCODE != a.BARCODE));

【问题讨论】:

标签: c# linq


【解决方案1】:

一种选择是使用集合操作,即

var result = new HashSet<Helper>(barcodesSource);
result.ExceptWith(barcodesTarget);

【讨论】:

    【解决方案2】:

    您可以使用 LINQ .Except() 方法和自定义 Comparer 类:

       class Helper
        {
            public string barCode;
        }
    
        class MyComparer : IEqualityComparer<Helper>
        {
            public bool Equals(Helper x, Helper y)
            {
                return x.barCode == y.barCode;
            }
    
            public int GetHashCode(Helper obj)
            {
                return obj.GetHashCode();
            }
        }
    
        class Class1
        {
            static void Main()
            {
                List<Helper> bcs1 = new List<Helper>()
                {
                    new Helper() { barCode = "0001" },
                    new Helper() { barCode = "0002" },
                    new Helper() { barCode = "0003" },
                    new Helper() { barCode = "0004" }
                };
    
                List<Helper> bcs2 = new List<Helper>()
                {
                    new Helper() { barCode = "0001" },
                    new Helper() { barCode = "0002" },
                    new Helper() { barCode = "0003" }
                };
    
                bcs1 = bcs1.Except(bcs2, new MyComparer()).ToList();
    
                Console.WriteLine(bcs1.Count);    
                Console.WriteLine(bcs1.First().barCode);
    
                Console.ReadKey();
            }
        }
    

    输出: 1 0004

    【讨论】:

    • 而不是 return base.GetHashCode();return BARCODE.GetHashCode(); 因为 OP 只关心 BARCODE 值而不是 Helper 类的相应 ITEM 值。
    • @JenishRabadiya 好点,虽然 OP 只是想获得两个集合之间的差异
    【解决方案3】:

    您可以在 Lambda 表达式中使用 Join 来获取相同的 Helper 对象。

    barcodesSource.Join(barcodesTarget, x=> new {x.BARCODE, x.ITEM}, y=> new {y.BARCODE, y.ITEM}, (x,y)=> x);
    

    你可以使用这个辅助方法来获取不同的对象:

    public static IEnumerable<TOuter> NotJoin<TOuter, TInner, TKey>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector)
        where TInner : class
        where TOuter : class
    {
        IEnumerable<TOuter> results = from o in outer join i in inner on outerKeySelector(o) equals innerKeySelector(i) into joinData from left in joinData.DefaultIfEmpty() where left == null select o;
        return results;
    }
    
    barcodesSource.NotJoin(barcodesTarget, x=> new {x.BARCODE, x.ITEM}, y=> new {y.BARCODE, y.ITEM});
    

    【讨论】:

      【解决方案4】:

      使用HashSet&lt;&gt;.Contains 的另一种基于集合的方法:

      var barcodes = new HashSet<long>(barcodesTarget.Select(b => b.BARCODE));
      var distinctBarcodes = barcodesSource.Where(a => !barcodes.Contains(a.BARCODE));
      

      【讨论】:

      • 谢谢。它解决了我的问题。
      【解决方案5】:

      使用Any:

      var distinctBarcodes = barcodesSource.Where(a => !barcodesTarget.Any(b => b.BARCODE == a.BARCODE));
      

      【讨论】:

      • 不知道为什么这会得到如此多的赞成,因为它会产生O(N2)(或接近)的复杂性,这是不可取的,如果两个集合都很大,可能会导致性能问题。
      • @Fabjan,当然,您可以使用 O(NlogN) 订购两者,并且通过一次就可以做到,但这不是 CS 问题。我对数据和数量一无所知。在大多数情况下,提供的解决方案都可以正常工作。
      • 如果我使用或编码,我将进入结果视图错误函数评估已禁用,因为之前的函数评估超时。您必须继续执行才能重新启用函数评估。一个集合有超过 64 000 行,其他大约 60 000 行。
      • @VladimirToth,只需在谷歌中搜索错误。这里有两个答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-05
      • 2021-12-20
      • 2014-12-10
      • 2017-04-01
      • 1970-01-01
      相关资源
      最近更新 更多