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

时间:2009-10-10 03:14:23

标签: c# .net collections comparison equality

除了逐个单步执行元素之外,如何比较两个字符串列表是否相等(在.NET 3.0中):

这失败了:

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

9 个答案:

答案 0 :(得分:76)

尝试以下

var equal = expected.SequenceEqual(actual);

测试版

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

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

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

答案 1 :(得分:40)

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

CollectionAssert.AreEqual(expected, actual);

E.g MS Test

答案 2 :(得分:12)

您可以随时自行编写所需的功能:

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

并使用它:

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

答案 3 :(得分:10)

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

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

答案 4 :(得分:5)

如果订单很重要:

bool equal = a.SequenceEquals(b);

如果订单无关紧要:

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

答案 5 :(得分:1)

您可以编写如下的扩展方法:

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

并称之为:

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

编辑:更新代码以使用静态方法,因为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;
        }

客户端:

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

答案 6 :(得分:1)

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

def fib(n):
    if n == 0:
        return [0]
    elif n == 1:
        return [0, 1]
    else:
        lst = fib(n-1)
        lst.append(lst[-1] + lst[-2])
        return lst

答案 7 :(得分:0)

虽然它会迭代集合,但我创建的这个扩展方法并不要求两个列表的顺序相同,只要重写了Equals方法,它也适用于复杂类型。

以下两个列表将返回true:

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

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

方法:

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

答案 8 :(得分:0)

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

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

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

也不要忘记为自定义类型实现IEquatable接口(对于字符串类型或其他结构不是必需的)