Как сортируется метод LINQ .distinct? - PullRequest
13 голосов
/ 05 ноября 2010

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

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

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

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

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

Ответы [ 5 ]

20 голосов
/ 05 ноября 2010

Предполагая, что вы имеете в виду 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.

8 голосов
/ 05 ноября 2010

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

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

3 голосов
/ 05 ноября 2010

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

1 голос
/ 05 ноября 2010

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

1 голос
/ 05 ноября 2010

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

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

...