Есть ли встроенный метод для сравнения коллекций? - PullRequest
164 голосов
/ 04 сентября 2008

Я хотел бы сравнить содержимое пары коллекций в моем методе Equals. У меня есть словарь и IList. Есть ли встроенный метод для этого?

Отредактировано: Я хочу сравнить два словаря и два IList, поэтому я думаю, что означает равенство, ясно - если два словаря содержат одинаковые ключи, сопоставленные с одинаковыми значениями, то они равны.

Ответы [ 14 ]

0 голосов
/ 09 июня 2018

Не было, нет и не может быть, по крайней мере, я бы поверил в это. Причина заключается в том, что равенство коллекций, вероятно, определяется пользователем.

Элементы в коллекциях не должны быть в определенном порядке, хотя они имеют естественный порядок, это не то, на что должны опираться алгоритмы сравнения. Скажем, у вас есть две коллекции:

{1, 2, 3, 4}
{4, 3, 2, 1}

Они равны или нет? Вы должны знать, но я не знаю, какова ваша точка зрения.

Коллекции концептуально неупорядочены по умолчанию, пока алгоритмы не предоставляют правила сортировки. То же самое, что SQL-сервер предлагает вашему вниманию, когда вы пытаетесь сделать нумерацию страниц, вам нужно предоставить правила сортировки:

https://docs.microsoft.com/en-US/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-2017

Еще две коллекции:

{1, 2, 3, 4}
{1, 1, 1, 2, 2, 3, 4}

Опять они равны или нет? Вы говорите мне ..

Повторяемость элементов коллекции играет свою роль в различных сценариях, и некоторые коллекции, такие как Dictionary<TKey, TValue>, даже не допускают повторения элементов.

Я полагаю, что эти виды равенства определяются приложением, и поэтому структура не обеспечивала все возможные реализации.

Ну, в общем случае Enumerable.SequenceEqual достаточно хорошо, но возвращает false в следующем случае:

var a = new Dictionary<String, int> { { "2", 2 }, { "1", 1 }, };
var b = new Dictionary<String, int> { { "1", 1 }, { "2", 2 }, };
Debug.Print("{0}", a.SequenceEqual(b)); // false

Я прочитал некоторые ответы на подобные вопросы (вы можете google для них) и что бы я использовал, в общем:

public static class CollectionExtensions {
    public static bool Represents<T>(this IEnumerable<T> first, IEnumerable<T> second) {
        if(object.ReferenceEquals(first, second)) {
            return true;
        }

        if(first is IOrderedEnumerable<T> && second is IOrderedEnumerable<T>) {
            return Enumerable.SequenceEqual(first, second);
        }

        if(first is ICollection<T> && second is ICollection<T>) {
            if(first.Count()!=second.Count()) {
                return false;
            }
        }

        first=first.OrderBy(x => x.GetHashCode());
        second=second.OrderBy(x => x.GetHashCode());
        return CollectionExtensions.Represents(first, second);
    }
}

Это означает, что одна коллекция представляет другую в своих элементах, включая повторяющиеся моменты времени, без учета первоначального порядка. Некоторые замечания о реализации:

  • GetHashCode() только для порядка, а не для равенства; Я думаю, что в этом случае достаточно

  • Count() на самом деле не будет перечислять коллекцию и напрямую попадет в реализацию свойства ICollection<T>.Count

  • Если ссылки равны, это просто Борис

0 голосов
/ 13 марта 2016
public bool CompareStringLists(List<string> list1, List<string> list2)
{
    if (list1.Count != list2.Count) return false;

    foreach(string item in list1)
    {
        if (!list2.Contains(item)) return false;
    }

    return true;
}
0 голосов
/ 04 сентября 2008

Нет. Структура коллекции не имеет понятия равенства. Если вы думаете об этом, нет способа сравнить коллекции, которые не являются субъективными. Например, сравнивая ваш IList с вашим словарем, будут ли они равны, если все ключи были в IList, все значения были в IList или оба были в IList? Не существует очевидного способа сравнения этих двух коллекций без знания того, для чего они будут использоваться, поэтому метод равенства общего назначения не имеет смысла.

0 голосов
/ 04 сентября 2008

Нет, потому что фреймворк не знает, как сравнивать содержимое ваших списков.

Посмотрите на это:

http://blogs.msdn.com/abhinaba/archive/2005/10/11/479537.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...