Я использую инструкции LINQ to Objects для упорядоченного массива. Какие операции не следует делать, чтобы убедиться, что порядок массива не изменился?
Я использую инструкции LINQ to Objects для упорядоченного массива. Какие операции не следует делать, чтобы убедиться, что порядок массива не изменился?
Ответы:
Я исследовал методы System.Linq.Enumerable , отбрасывая все, которые возвращали не IEnumerable результаты. Я проверил замечания каждого из них, чтобы определить, как порядок результата будет отличаться от порядка источника.
Сохраняет порядок абсолютно. Вы можете сопоставить исходный элемент по индексу с результирующим элементом
Сохраняет заказ. Элементы фильтруются или добавляются, но не переупорядочиваются.
Уничтожает порядок - мы не знаем, в каком порядке следует ожидать результатов.
Переопределить порядок явным образом - используйте их, чтобы изменить порядок результата
Переопределяет заказ в соответствии с некоторыми правилами.
Изменить: я переместил 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;
}
Distinct
метода) просто означает «не отсортировано», а не «в непредсказуемом порядке». Я бы сказал, Distinct
относится к категории фильтрации выше, как и Where
.
Вы на самом деле говорите о SQL или о массивах? Иными словами, вы используете LINQ to SQL или LINQ to Objects?
Операторы LINQ to Objects фактически не изменяют свой исходный источник данных - они создают последовательности, которые эффективно поддерживаются источником данных. Единственными операциями, которые изменяют порядок, являются OrderBy / OrderByDescending / ThenBy / ThenByDescending - и даже тогда они стабильны для одинаково упорядоченных элементов. Конечно, многие операции отфильтруют некоторые элементы, но возвращаемые элементы будут в том же порядке.
Если вы преобразуете в другую структуру данных, например, с помощью ToLookup или ToDictionary, я не верю, что порядок сохраняется в этот момент - но это все равно несколько иначе. (Порядок отображения значений для одного и того же ключа сохраняется для поиска, хотя, я считаю.)
GroupBy
затем SelectMany
дадут результаты , сгруппированные по ключу, но не в порядке возрастания ключа ... он даст их в том порядке , в котором ключи первоначально имели место.
list<x> {a b c d e f g}
если в c, d, e все ключи имеют одинаковый ключ, то результирующая последовательность будет содержать c, d, e рядом друг с другом И в порядке c, d, e. Я не могу найти категорический ответ на основе MS.
Если вы работаете с массивом, похоже, что вы используете LINQ-to-Objects, а не SQL; Можешь подтвердить? Большинство операций LINQ ничего не упорядочивают (выходные данные будут в том же порядке, что и входные), поэтому не применяйте другую сортировку (OrderBy [Descending] / ThenBy [Descending]).
[править: как выразился Джон более четко; LINQ обычно создает новую последовательность, оставляя исходные данные в покое]
Обратите внимание, что Dictionary<,>
вставка данных в (ToDictionary) будет шифровать данные, так как словарь не учитывает какой-либо конкретный порядок сортировки.
Но наиболее распространенные вещи (выбрать, где, пропустить, взять) должны быть в порядке.
ToDictionary()
просто не дает никаких обещаний о порядке, но на практике поддерживает порядок ввода (пока вы не удалите что-либо из него). Я не говорю, чтобы полагаться на это, но «карабкаться» кажется неточным.
Я нашел отличный ответ в аналогичном вопросе, который ссылается на официальную документацию. Процитирую это:
Для Enumerable
методов (LINQ к объектам, который относится к List<T>
), вы можете полагаться на порядок элементов , возвращаемых Select
, Where
или GroupBy
. Это не относится к вещам, которые по своей природе неупорядочены, как ToDictionary
или Distinct
.
Из документации Enumerable.GroupBy :
Эти
IGrouping<TKey, TElement>
объекты получены в порядке , основанном на порядок элементов в источнике , которые произвели первый ключ каждогоIGrouping<TKey, TElement>
. Элементы в группировке приводятся в порядке их появленияsource
.
Это не обязательно верно для IQueryable
методов расширения (другие поставщики LINQ).
Источник: Поддерживают ли перечисляемые методы LINQ относительный порядок элементов?
Вопрос здесь конкретно относится к LINQ-to-Objects.
Если вы используете LINQ-to-SQL вместо этого, там нет порядка, если вы не навязываете что-то вроде:
mysqlresult.OrderBy(e=>e.SomeColumn)
Если вы не сделаете это с LINQ-to-SQL, то порядок результатов может отличаться для последующих запросов, даже для тех же данных, что может вызвать прерывистую ошибку.