C# 比较两个 List<string> 是否相等

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1546925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 18:43:09  来源:igfitidea点击:

Comparing two List<string> for equality

c#.netcollectionscomparisonequality

提问by Adam Kane

Other than stepping through the elements one by one, how do I compare two lists of strings for equality (in .NET 3.0):

除了一一遍历元素之外,我如何比较两个字符串列表的相等性(在 .NET 3.0 中):

This fails:

这失败了:

// Expected result.
List<string> expected = new List<string>();
expected.Add( "a" );
expected.Add( "b" );
expected.Add( "c" );

// Actual result
actual = new List<string>();
actual.Add( "a" );
actual.Add( "b" );
actual.Add( "c" );

// Verdict
Assert.IsTrue( actual == expected );

采纳答案by dahlbyk

Many test frameworks offer a CollectionAssert class:

许多测试框架提供了一个 CollectionAssert 类:

CollectionAssert.AreEqual(expected, actual);

E.g MS Test

例如MS 测试

回答by JaredPar

Try the following

尝试以下

var equal = expected.SequenceEqual(actual);

Test Version

测试版

Assert.IsTrue( actual.SequenceEqual(expected) );

The SequenceEqual extension method will compare the elements of the collection in order for equality.

SequenceEqual 扩展方法将比较集合的元素以确保相等。

See http://msdn.microsoft.com/en-us/library/bb348567(v=vs.100).aspx

请参阅http://msdn.microsoft.com/en-us/library/bb348567(v=vs.100).aspx

回答by AndreyAkinshin

You can always write the needed function themselves:

您始终可以自己编写所需的函数:

public static bool ListEquals<T>(IList<T> list1, IList<T> list2) {
    if (list1.Count != list2.Count)
        return false;
    for (int i = 0; i < list1.Count; i++)
        if (!list1[i].Equals(list2[i]))
            return false;
    return true;
}

and use it:

并使用它:

// Expected result.
List<string> expected = new List<string>();
expected.Add( "a" );
expected.Add( "b" );
expected.Add( "c" );

// Actual result
actual = new List<string>();
actual.Add( "a" );
actual.Add( "b" );
actual.Add( "c" );

// Verdict
Assert.IsTrue( ListEquals(actual, expected) );

回答by bobbymcr

I noticed no one actually told you why your original code didn't work. This is because the ==operator in general tests reference equality(i.e. if the two instances are pointing to the same object in memory) unless the operator has been overloaded. List<T>does not define an ==operator so the base reference equals implementation is used.

我注意到没有人真正告诉你为什么你的原始代码不起作用。这是因为==运算符通常会测试引用相等性(即,如果两个实例指向内存中的同一个对象),除非运算符已重载List<T>未定义==运算符,因此使用基本引用等于实现。

As other posters have demonstrated, you will generally have to step through elements to test "collection equality." Of course, you should use the optimization suggested by user DreamWalkerwhich first tests the Count of the collections before stepping through them.

正如其他海报所展示的那样,您通常必须逐步遍历元素来测试“收藏平等”。当然,您应该使用用户DreamWalker建议的优化,它在单步执行之前首先测试集合的计数。

回答by Abhijeet Patel

You could write an extension method like so:

您可以像这样编写扩展方法:

public static class ListExtensions
    {
        public static bool IsEqual<T>(this IList<T> list,IList<T> target, IComparer<T> comparer) where T:IComparable<T>
        {
            if (list.Count != target.Count)
            {
                return false;
            }
            int index = 0;
            while (index < list.Count && 
                   comparer.Compare(list[index],target[index]) == 0)
            {
                index++;
            }
            if (index != list.Count)
            {
                return false;
            }
            return true;
        }
    }

And call it like so:

并这样称呼它:

List<int> intList = new List<int> { 1, 234, 2, 324, 324, 2 };
List<int> targetList = new List<int> { 1, 234, 2, 324, 324 };
bool isEqual = intList.IsEqual(targetList, Comparer<int>.Default);

EDIT: Updated the code to use a static method instead since OP is using .NET 3.0

编辑:更新代码以使用静态方法,因为 OP 使用 .NET 3.0

public static bool IsEqual<T>(IList<T> sourceList, IList<T> targetList, IComparer<T> comparer) where T : IComparable<T>
        {
            if (sourceList.Count != targetList.Count)
            {
                return false;
            }
            int index = 0;
            while (index < sourceList.Count &&
                   comparer.Compare(sourceList[index], targetList[index]) == 0)
            {
                index++;
            }
            if (index != sourceList.Count)
            {
                return false;
            }
            return true;
        }

Client:

客户:

        bool isEqual = IsEqual(intList,targetList, Comparer<int>.Default);

回答by Johnie Karr

While it does iterate over the collection, this extension method I created does not require the order of the two lists to be the same, and it works with complex types as well, as long as the Equals method is overridden.

虽然它确实遍历集合,但我创建的这个扩展方法不需要两个列表的顺序相同,并且它也适用于复杂类型,只要覆盖 Equals 方法即可。

The following two lists would return true:

以下两个列表将返回 true:

List<string> list1 = new List<string>
{
    { "bob" },
    { "sally" },
    { "john" }
};

List<string> list2 = new List<string>
{
    { "sally" },
    { "john" },
    { "bob" }
};

Method:

方法:

public static bool IsEqualTo<T>(this IList<T> list1, IList<T> list2)
{
    if (list1.Count != list2.Count)
    {
        return false;
    }

    List<T> list3 = new List<T>();

    foreach (var item in list2)
    {
        list3.Add(item);
    }

    foreach (var item in list1)
    {
        int index = -1;
        for (int x = 0; x < list3.Count; x++)
        {
            if (list3[x].Equals(item))
            {
                index = x;
            }
        }

        if (index > -1)
        {
            list3.RemoveAt(index);
        }
        else
        {
            return false;
        }
    }

    return !list3.Any();
}

回答by Olivier

Using Linq and writing the code as an extension method :

使用 Linq 并将代码编写为扩展方法:

public static bool EqualsOtherList<T>(this List<T> thisList, List<T> theOtherList)
{
  if (thisList == null || theOtherList == null || 
      thisList.Count != theOtherList.Count) return false;
  return !thisList.Where((t, i) => !t.Equals(theOtherList[i])).Any();
}

回答by Gaui

If the order matters:

如果订单很重要:

bool equal = a.SequenceEquals(b);

If the order doesn't matter:

如果顺序无关紧要:

bool equal = a.Count == b.Count && new HashSet<string>(a).SetEquals(b);

回答by Oleg Bondarenko

It might be used with not regular way but without implementation IEquatable for Custom types

它可能不以常规方式使用,但没有为自定义类型实现 IEquatable

JsonConvert.SerializeObject( myList1) == JsonConvert.SerializeObject( myList2)

But in general case you could use SequenceEqual as was mentioned in comments https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.sequenceequal?view=netframework-4.8

但在一般情况下,您可以使用 SequenceEqual,如评论中提到的https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.sequenceequal?view=netframework-4.8

Also do not forget to implement IEquatable interface for custom types (not necessary for strings type or other structure)

另外不要忘记为自定义类型实现 IEquatable 接口(字符串类型或其他结构不需要)