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

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

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

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

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

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

Ответы

Ответ 1

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

Ответ 2

docs говорят:

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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