Как сортируется метод LINQ .distinct?

Допустим, я использую метод массива LINQ .Distinct(). Результат неупорядочен.

Что ж, все «упорядочено», если вы знаете логику, используемую для получения результата.

Мой вопрос касается набора результатов. Будет ли результирующий массив находиться в «первом отдельном» порядке или, возможно, в «последнем отдельном» порядке?

Могу ли я никогда не рассчитывать ни на какой заказ?

Это старая проблема «удалить повторяющиеся строки», но я изучаю решение LINQ.


person Matthew    schedule 05.11.2010    source источник


Ответы (5)


Предполагая, что вы имеете в виду LINQ to Objects, он в основном сохраняет набор всех результатов, которые он возвращал до сих пор, и дает «текущий» элемент, только если он не был получен ранее. Таким образом, результаты находятся в исходном порядке, дубликаты удалены. Что-то вроде этого (кроме проверки ошибок и т.д.):

public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source)
{
    HashSet<T> set = new HashSet<T>();

    foreach (T item in source)
    {
        if (set.Add(item))
        {
            // New item, so yield it
            yield return item;
        }
    }
}

Это не гарантируется, но я не могу представить себе более разумную реализацию. Это позволяет Distinct() быть настолько ленивым, насколько это возможно — данные возвращаются, как только это возможно, и буферизуется только минимальный объем данных.

Полагаться на это было бы плохой идеей, но может быть полезно узнать, как работает текущая реализация (очевидно). В частности, вы можете легко заметить, что он начинает возвращать данные до исчерпания исходной последовательности, просто создавая источник, который записывает в журнал, когда он создает данные для использования Distinct, а также регистрирует, когда вы получать данные от Distinct.

person Jon Skeet    schedule 05.11.2010
comment
Вы также можете просто добавить свой собственный метод расширения (например, DistinctOrdered‹T›) с реализацией, предоставленной Джоном. Таким образом, у вас всегда будет реализация с определенным порядком, независимо от версии .NET Framework. - person Karsten; 04.11.2015
comment
добавление к фактам о Джоне Ските - Справочный источник .NET основан на ответах Джона Скита. - person Slai; 17.01.2017

документы говорят:

«Последовательность результатов неупорядочена».

person Gabriel Magana    schedule 05.11.2010
comment
Я знаю это. Я хочу сказать, что представление о том, что порядок является случайным, на самом деле не выдерживает критики... если только этот метод не является чем-то совершенно чуждым мне. - person Matthew; 05.11.2010
comment
@matthew: Хорошо, но вы спрашиваете, могу ли я никогда не рассчитывать ни на какой заказ? Поскольку в документах четко указано, что результат неупорядочен, то рассчитывать на какой-либо порядок нельзя. Если сегодня он находится в определенном порядке, со следующим исправлением ошибки .NET это может измениться, поскольку нет гарантии порядка. - person Gabriel Magana; 05.11.2010
comment
@matthew: проверьте ответ Джона. В лучшем случае порядок совпадает с порядком, в котором поступали данные, но, как все говорят, и согласно документам, нет гарантии какого-либо конкретного порядка. Если вам нужен порядок, добавьте OrderBy в Linq, например. var result = sourceItems.Distinct().OrderBy(item => item.ValueToOrderOn) - person Will; 06.11.2010

Никогда нельзя рассчитывать ни на какой заказ. Для LINQ было бы вполне допустимо реализовать это с помощью хеш-таблиц (и действительно, я считаю, что это реализовано таким образом в .NET 4).

person Billy ONeal    schedule 05.11.2010

Насколько мне известно, метод Distinct официально не гарантирует порядок, хотя на практике реализация LINQ to Objects возвращает группы в том порядке, в котором они впервые появляются в перечислимом источнике.

Например, если вы используете LINQ to SQL, то база данных должна решить, в каком порядке она хочет вернуть результаты, и тогда вам не следует полагаться на этот порядок, даже если он непротиворечив от одного вызова к другому.

person Mark Byers    schedule 05.11.2010

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

person Jerry Coffin    schedule 05.11.2010