Подтвердить что ты не робот

Сравнение двух List <string> для равенства

Кроме того, что один шаг за шагом перебирает элементы, как сравнить два списка строк для равенства (в .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 );
4b9b3361

Ответ 1

Многие тестовые среды предлагают класс CollectionAssert:

CollectionAssert.AreEqual(expected, actual);

E.g MS Test

Ответ 2

Попробуйте выполнить

var equal = expected.SequenceEqual(actual);

Версия для тестирования

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

Метод расширения SequenceEqual будет сравнивать элементы коллекции для равенства.

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

Ответ 3

Вы всегда можете сами написать нужную функцию:

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

Ответ 4

Я заметил, что никто на самом деле не сказал вам, почему ваш исходный код не работает. Это связано с тем, что оператор == в общих тестах ссылка равенство (т.е. если оба экземпляра указывают на один и тот же объект в памяти), если только оператор был перегружен. List<T> не определяет оператор ==, поэтому используется базовая ссылка равна реализации.

Как показали другие плакаты, вам, как правило, приходится проходить через элементы, чтобы проверить "равенство коллекции". Разумеется, вы должны использовать оптимизацию, предложенную пользователем DreamWalker, которая сначала проверяет количество коллекций перед их прохождением.

Ответ 5

Если порядок имеет значение:

bool equal = a.SequenceEquals(b);

Если порядок не имеет значения:

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

Ответ 6

Вы можете написать метод расширения следующим образом:

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

EDIT: Обновлен код, чтобы использовать статический метод, поскольку 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);

Ответ 7

Использование 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

Пока он выполняет итерацию по коллекции, этот метод расширения, который я создал, не требует, чтобы порядок двух списков был одинаковым, и он также работает со сложными типами, если метод 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();
}