Сохранение заказа с помощью LINQ

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

Ответ 1

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

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

  • AsEnumerable
  • В ролях
  • Concat
  • Выберите
  • ToArray
  • ToList

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

  • Distinct
  • За исключением
  • Intersect
  • OfType
  • Пропустить
  • SkipWhile
  • Возьмите
  • TakeWhile
  • Где
  • Почтовый индекс (новый в .net 4)

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

  • ToDictionary
  • ToLookup

Неопределенно переопределяет порядок - используйте их, чтобы изменить порядок результата

  • OrderBy
  • OrderByDescending
  • Reverse
  • ThenBy
  • ThenByDescending

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

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

Изменить: я переместил команду Distinct в Preserving на основе этой реализации.

    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;
    }

Ответ 2

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

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

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

Ответ 3

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

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

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

Но наиболее распространенные вещи (Select, Where, Skip, Take) должны быть в порядке.

Ответ 4

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

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

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

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

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

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

Ответ 5

Любая "группа" или "порядок" может изменить порядок.

Ответ 6

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

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

mysqlresult.OrderBy(e=>e.SomeColumn)

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