简体   繁体   English

检查2个列表的快速方法是相同的c#

[英]Quick way to check 2 lists are the same c#

Suppose there are these two strongly typed lists: 假设有两个强类型列表:

List 1 : existingitems 清单1:现有项目

ID, Name, Cat ID,姓名,Cat
1, ABC, C 1,ABC,C
2, BCD, D 2,BCD,D
3, NNN, F 3,NNN,F

List 2 : newitems 清单2:newitems

ID, Name, Cat ID,姓名,Cat
9, ABC, C 9,ABC,C
15, BCD, D 15,BCD,D
12, NNN, F 12,NNN,F

Basically, I want to check that the Name and Cat values are the same in both lists. 基本上,我想检查两个列表中的Name和Cat值是否相同。 If the two lists are identical on these two columns, return true, otherwise false. 如果这两个列在这两列上相同,则返回true,否则返回false。

I'd tried a few variations mostly around the below but always seems to return true, even is the newitems list has a new row, which I would expect to return false. 我尝试了一些主要在下面的变化,但似乎总是返回true,即使是newitems列表有一个新行,我希望返回false。

newitems.Any(x1 => existingitems.All(x2 => (x1.Name== x2.Name) && (x1.Cat== x2.Cat)));

I believe this is probably the cleanest and simplest solution for you. 我相信这对您来说可能是最干净,最简单的解决方案。

var list1Subset = list1.Select(i => new {i.Name, i.Cat});
var list2Subset = list2.Select(i => new {i.Name, i.Cat});

bool equal = list1Subset.SequenceEqual(list2Subset);

You can do this efficiently with a HashSet and custom comparer: 您可以使用HashSet和自定义比较器有效地执行此操作:

public class ItemComparer : IEqualityComparer<Item>
{
    public bool Equals(Item x, Item y)
    {
        return (x.Cat == y.Cat) && (x.Name == y.Name);
    }

    public int GetHashCode(Item obj)
    {
        return (obj.Cat.GetHashCode() * 17) + (obj.Name.GetHashCode() * 17);
    }
}

public bool AreEqual(IEnumerable<T> set1, IEnumerable<T> set2, 
    IEqualityComparer<T> equalityComparer)
{
    // Handle cheapest cases
    if (set1 == null && set2 == null)
    {
        return true;
    }
    else if (set1 == null && set2 != null
        || set1 != null && set2 == null)
    {
        return false;
    }
    else if (object.ReferenceEquals(set1, set2))
    {
        return true;
    }

    var hashSet1 = new HashSet<T>(set1, equalityComparer);
    var hashSet2 = new HashSet<T>(set2, equalityComparer);

    // More easy cases
    if (hashSet1.Count != hashSet2.Count)
    {
        return false;
    }

    if (set1.Any(i => !hashSet2.Contains(i))
        || set2.Any(i => !hashSet1.Contains(i)))
    {
        return false;
    }

    return true;
}
var areEqual = !existingitems.Select(x => new { x.Name, x, Cat })
                       .Except(newItems.Select(x => new { x.Name, x, Cat }))
                       .Any() 
             && !newItems.Select(x => new { x.Name, x, Cat })
                       .Except(existingitems.Select(x => new { x.Name, x, Cat }))
                       .Any();

or 要么

var areEqual
     = newItems.Select(x => new { x.Name, x, Cat })
               .OrderBy(x => x.Name)
               .ThenBy(x => x.Cat)
               .SequanceEquals(existingitems.Select(x => new { x.Name, x, Cat })
                                       .OrderBy(x => x.Name)
                                       .ThenBy(x => x.Cat));

We can first define a method to determine if two sequences are equal sets: 我们可以先定义一个方法来确定两个序列是否是相等的集合:

public static bool SetEquals<T>(this IEnumerable<T> first
    , IEnumerable<T> second
    , IEqualityComparer<T> comparer = null)
{
    comparer = comparer ?? EqualityComparer<T>.Default;
    return new HashSet<T>(second).SetEquals(first);
}

Then we can filter out the fields that you want and perform the set equality on that projection: 然后我们可以过滤掉您想要的字段并在该投影上执行集合相等:

var areEqual = list1.Select(item => new{item.Name, item.Cat})
    .SetEquals(list2.Select(item => new{item.Name, item.Cat}));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM