linq 检查两个列表是否有相同的项目

9wbgstp7  于 2023-01-10  发布在  其他
关注(0)|答案(6)|浏览(233)

我有两个整数列表,list1和list2。列表中的元素是相同的,但顺序并不重要。忽略元素的顺序,我如何判断这两个列表是否相等?C#中是否有内置方法可以做到这一点,或者我需要自己编写方法?

var list1 = new List<int> {1,2,3};
var list2 = new List<int> {2,1,3};
bfhwhh0e

bfhwhh0e1#

这就是集合(例如HashSet<T>)的作用,集合没有定义的顺序,SetEquals验证集合和另一个集合是否包含相同的元素。

var set = new HashSet<int>(list1);
var equals = set.SetEquals(list2);
lb3vh1jj

lb3vh1jj2#

您可以使用!Except + Any

bool list1InList2 = !list1.Except(list2).Any();

这不是检查两者是否具有相同的项,而是检查list1是否包含在list2中(忽略重复项)。
如果要了解list2是否包含在list1中,请使用:

bool list2InList1 = !list2.Except(list1).Any();

因此,如果要确保两个列表包含相同的项,就必须同时进行这两项检查。
如果你还想考虑到两个列表的大小是一样的,可以使用list1.Count==list2.Count进行预检查,但是如果你使用set方法(参见Harald's comment),这个检查就没有用了,如果你忽略了重复项,比较计数就没有多大意义了。
一般来说,HashSet<T>有一些很好的和有效的方法来检查两个序列是否有相同的项(忽略重复项),dcastro already showed是一个。
如果您想要一个有效的解决方案来确定两个列表是否包含相同的项,相同的计数不忽略重复项忽略顺序(否则使用SequenceEquals):

public static bool SequenceEqualsIgnoreOrder<T>(this IEnumerable<T> list1, IEnumerable<T> list2, IEqualityComparer<T> comparer = null)
{
    if(list1 is ICollection<T> ilist1 && list2 is ICollection<T> ilist2 && ilist1.Count != ilist2.Count)
        return false;

    if (comparer == null)
        comparer = EqualityComparer<T>.Default;

    var itemCounts = new Dictionary<T, int>(comparer);
    foreach (T s in list1)
    {
        if (itemCounts.ContainsKey(s))
        {
            itemCounts[s]++;
        }
        else
        {
            itemCounts.Add(s, 1);
        }
    }
    foreach (T s in list2)
    {
        if (itemCounts.ContainsKey(s))
        {
            itemCounts[s]--;
        }
        else
        {
            return false;
        }
    }
    return itemCounts.Values.All(c => c == 0);
}

用法:

var list1 = new List<int> { 1, 2, 3, 1 };
var list2 = new List<int> { 2, 1, 3, 2 };
bool sameItemsIgnoringOrder = list1.SequenceEqualsIgnoreOrder(list2); 
// false because same count and same items but 1 appaears twice in list1 but once in list2

如果顺序很重要并且重复项也很重要,请使用:

bool sameItemsSameOrder = list1.SequenceEqual(list2);
vsikbqxv

vsikbqxv3#

不使用linq。

private static bool AreListsEqual(List<int> list1, List<int> list2)
 {
        var areListsEqual = true;

        if (list1.Count != list2.Count)
            return false;

        for (var i = 0; i < list1.Count; i++)
        {
            if (list2[i] != list1[i])
            {
                areListsEqual = false;
            }
        }

        return areListsEqual;
 }
q0qdq0h2

q0qdq0h24#

对有序列表使用SequenceEqual-例如

bool equal = list1.OrderBy(x => x).ToList().SequenceEqual(list2.OrderBy(x => x).ToList());
8yparm6h

8yparm6h5#

这是旧的,但我会修改由dcastro的答案,并在extension构建:

public static bool CompareList(this List<string> _initialList, List<string> _secondaryList) 
{ 
    var set = new HashSet<string>(_initialList); 
    var equals = set.SetEquals(_secondaryList); 
    return equals ? _initialList.Count() == _secondaryList.Count() : false; 
}

这样,您将使用集合检查列表中的两个元素,而且元素计数有助于您检查注解中给出的示例,如***{0,1,1} vs {0,1}***
此外,通过扩展,您可以在代码中多次调用它。您可以修改它以与潜在的null进行比较。

public static bool CompareList(this List<string> _initialList, List<string>? _secondaryList) 
{
    //test if _secondaryList is null while initial is not
    if (_secondaryList == null) return false;

    var set = new HashSet<string>(_initialList); 
    var equals = set.SetEquals(_secondaryList); 
    return equals ? _initialList.Count() == _secondaryList.Count() : false; 
}
jckbn6z7

jckbn6z76#

您可以尝试Except

var result = list1.Except(list2).ToList();

Except返回first中未出现在second中的元素

相关问题