比较两个List 是否相等

时间:2022-11-09 22:51:28

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 );

8 个解决方案

#1


40  

Many test frameworks offer a CollectionAssert class:

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

CollectionAssert.AreEqual(expected, actual);

E.g MS Test

例如,MS测试

#2


74  

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

#3


12  

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) );

#4


10  

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 没有定义==运算符,因此使用了基本引用等于实现。

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 DreamWalker which first tests the Count of the collections before stepping through them.

正如其他海报所展示的那样,你通常必须逐步通过元素来测试“集合平等”。当然,您应该使用用户DreamWalker建议的优化,该优化在逐步测试之前首先测试集合的Count。

#5


5  

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);

#6


1  

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);

#7


1  

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();
}

#8


0  

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();
}

#1


40  

Many test frameworks offer a CollectionAssert class:

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

CollectionAssert.AreEqual(expected, actual);

E.g MS Test

例如,MS测试

#2


74  

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

#3


12  

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) );

#4


10  

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 没有定义==运算符,因此使用了基本引用等于实现。

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 DreamWalker which first tests the Count of the collections before stepping through them.

正如其他海报所展示的那样,你通常必须逐步通过元素来测试“集合平等”。当然,您应该使用用户DreamWalker建议的优化,该优化在逐步测试之前首先测试集合的Count。

#5


5  

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);

#6


1  

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);

#7


1  

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();
}

#8


0  

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();
}