Я использую инструкции LINQ to Objects в упорядоченном массиве. Какие операции не следует делать, чтобы убедиться, что порядок массива не изменяется?
Сохранение заказа с помощью LINQ
Ответ 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, то порядок результатов может отличаться для последующих запросов, даже для одних и тех же данных, что может вызвать прерывистую ошибку.