Сохранение заказа с помощью LINQ - PullRequest
332 голосов
/ 15 октября 2008

Я использую инструкции LINQ to Objects для упорядоченного массива. Какие операции не следует выполнять, чтобы убедиться, что порядок массива не изменился?

Ответы [ 6 ]

586 голосов
/ 15 октября 2008

Я исследовал методы System.Linq.Enumerable , отбрасывая все, которые возвращали не-IEnumerable результаты. Я проверил замечания каждого из них, чтобы определить, как порядок результата будет отличаться от порядка источника.

Сохраняет заказ Абсолютно. Вы можете сопоставить исходный элемент по индексу с результирующим элементом

  • AsEnumerable
  • Cast
  • Concat
  • Выберите
  • ToList

Заказ на консервы. Элементы фильтруются, но не переупорядочиваются.

  • Четкая
  • За исключением
  • Intersect
  • Пропустить
  • SkipWhile
  • Take
  • Где * * 1040
  • Zip (новый в .net 4)

Уничтожает ордер - мы не знаем, в каком порядке ожидать результаты.

  • ToDictionary

Явно переопределяет порядок - используйте их для изменения порядка результата

  • OrderBy
  • OrderByDescending
  • Реверс
  • ThenBy
  • ThenByDescending

Переопределение заказа в соответствии с некоторыми правилами.

  • GroupBy - объекты IGrouping выдаются в порядке, основанном на порядке элементов в источнике, который создал первый ключ каждой IGrouping. Элементы в группировке приводятся в порядке их появления в источнике.
  • GroupJoin - GroupJoin сохраняет порядок элементов внешнего, а для каждого элемента внешнего - порядок соответствия элементов из внутреннего.
  • Join - сохраняет порядок элементов external, а для каждого из этих элементов порядок соответствия элементов inner.
  • SelectMany - для каждого элемента источника вызывается селектор и возвращается последовательность значений.
  • Union - при перечислении объекта, возвращаемого этим методом, Union перечисляет первый и второй в этом порядке и возвращает каждый элемент, который еще не был получен.

Редактировать: я переместил Distinct в Сохранение порядка на основе этой реализации .

    private static IEnumerable<TSource> DistinctIterator<TSource>
      (IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
    {
        Set<TSource> set = new Set<TSource>(comparer);
        foreach (TSource element in source)
            if (set.Add(element)) yield return element;
    }
31 голосов
/ 15 октября 2008

Вы на самом деле говорите об SQL или о массивах? Другими словами, используете ли вы LINQ to SQL или LINQ to Objects?

Операторы LINQ to Objects фактически не изменяют свой исходный источник данных - они создают последовательности, которые эффективно поддерживаются источником данных. Единственными операциями, которые изменяют порядок, являются OrderBy / OrderByDescending / ThenBy / ThenByDescending - и даже тогда они стабильны для одинаково упорядоченных элементов. Конечно, многие операции отфильтруют некоторые элементы, но возвращаемые элементы будут в том же порядке.

Если вы конвертируете в другую структуру данных, например, с ToLookup или ToDictionary я не верю, что порядок сохраняется в этот момент - но это все равно несколько иначе. (Порядок значений, сопоставляемых с одним и тем же ключом, сохраняется для поиска, хотя, я считаю.)

7 голосов
/ 15 октября 2008

Если вы работаете с массивом, похоже, что вы используете LINQ-to-Objects, а не SQL; Можешь подтвердить? Большинство операций LINQ ничего не упорядочивают (выходные данные будут в том же порядке, что и входные), поэтому не применяйте другой порядок (OrderBy [Descending] / ThenBy [Descending]).

[править: как выразился Джон; Обычно LINQ создает новую последовательность, оставляя только исходные данные]

Обратите внимание, что помещение данных в Dictionary<,> (ToDictionary) приведет к шифрованию данных, поскольку словарь не учитывает какой-либо конкретный порядок сортировки.

Но наиболее распространенные вещи (Выбрать, Где, Пропустить, Взять) должны быть в порядке.

3 голосов
/ 12 июня 2014

Я нашел отличный ответ в аналогичном вопросе, который ссылается на официальную документацию. Процитирую это:

Для методов Enumerable (LINQ to Objects, что относится к List<T>), вы можете положиться на порядок элементов, возвращаемых Select, Where или GroupBy. Это не относится к вещам, которые по своей природе неупорядочены, как ToDictionary или Distinct.

С Enumerable.GroupBy Документация:

Объекты IGrouping<TKey, TElement> выдаются в порядке, основанном на порядке элементов в источнике, который создал первый ключ каждого IGrouping<TKey, TElement>. Элементы в группировке выдаются в том порядке, в котором они отображаются в source.

Это не обязательно верно для IQueryable методов расширения (других провайдеров LINQ).

Источник: Поддерживают ли перечисляемые методы LINQ относительный порядок элементов?

2 голосов
/ 15 октября 2008

Любая 'group by' или 'order by', возможно, изменит порядок.

0 голосов
/ 19 мая 2019

Вопрос здесь специально относится к LINQ-to-Objects.

Если вы используете вместо этого LINQ-to-SQL, там нет порядка, если вы не навязываете его с чем-то вроде:

mysqlresult.OrderBy(e=>e.SomeColumn)

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

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