Używam LINQ do instrukcji Objects w uporządkowanej tablicy. Których operacji nie należy wykonywać, aby mieć pewność, że kolejność tablicy nie ulegnie zmianie?
361
Zbadałem metody System.Linq.Enumerable , odrzucając wszystkie, które zwróciły wyniki niepoliczalne dla IE . Sprawdziłem uwagi każdego z nich, aby ustalić, w jaki sposób kolejność wyniku różni się od kolejności źródła.
Całkowicie zachowuje porządek. Możesz zamapować element źródłowy według indeksu na element wynikowy
Zachowuje porządek. Elementy są filtrowane lub dodawane, ale nie są ponownie zamawiane.
Niszczy zamówienie - nie wiemy, w jakiej kolejności można oczekiwać.
Wyraźnie redefiniuje kolejność - użyj ich, aby zmienić kolejność wyników
Przedefiniowuje porządek zgodnie z niektórymi zasadami.
Edycja: W oparciu o tę implementację przeniosłem Distinct na Zachowanie kolejności .
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
metody) miała po prostu powiedzieć „nieposortowane”, a nie „w nieprzewidywalnej kolejności”. Powiedziałbym, żeDistinct
należy do powyższej kategorii filtrowania, podobnie jakWhere
.Czy faktycznie mówisz o SQL, czy o tablicach? Innymi słowy, czy używasz LINQ do SQL czy LINQ do Objects?
Operatorzy LINQ to Objects tak naprawdę nie zmieniają swojego oryginalnego źródła danych - budują sekwencje, które są skutecznie wspierane przez to źródło danych. Jedynymi operacjami, które zmieniają kolejność, są OrderBy / OrderByDescending / ThenBy / ThenByDescending - i nawet wtedy są stabilne dla równo uporządkowanych elementów. Oczywiście wiele operacji odfiltruje niektóre elementy, ale elementy, które zostaną zwrócone, będą w tej samej kolejności.
Jeśli przekonwertujesz na inną strukturę danych, np. Z ToLookup lub ToDictionary, nie sądzę, aby porządek został zachowany w tym momencie - ale i tak jest to nieco inne. (Wydaje mi się, że kolejność mapowania wartości na ten sam klucz jest zachowana dla wyszukiwania).
źródło
GroupBy
po nimSelectMany
podane zostaną wyniki pogrupowane według klucza, ale nie w rosnącej kolejności kluczy ... da to w kolejności, w której klucze wystąpiły pierwotnie.list<x> {a b c d e f g}
przypadku, gdy wszystkie c, d, e mają ten sam klucz, wynikowa sekwencja będzie zawierać c, d, e obok siebie ORAZ w kolejności c, d, e. Nie mogę znaleźć kategorycznej odpowiedzi opartej na stwardnieniu rozsianym.Jeśli pracujesz nad tablicą, wygląda na to, że używasz LINQ-to-Objects, a nie SQL; czy możesz potwierdzić? Większość operacji LINQ niczego nie porządkuje (dane wyjściowe będą w tej samej kolejności co dane wejściowe) - więc nie stosuj innego sortowania (OrderBy [Malejąco] / ThenBy [Malejąco]).
[edytuj: jak Jon uściślił; LINQ generalnie tworzy nową sekwencję, pozostawiając oryginalne dane w spokoju]
Zauważ, że wpychanie danych do
Dictionary<,>
(ToDictionary) będzie szyfrować dane, ponieważ słownik nie przestrzega żadnej szczególnej kolejności sortowania.Ale najczęstsze rzeczy (Wybierz, Gdzie, Pomiń, Weź) powinny być w porządku.
źródło
ToDictionary()
po prostu nie składa żadnych obietnic dotyczących kolejności, ale w praktyce utrzymuje kolejność wprowadzania (dopóki czegoś z niej nie usuniesz). Nie mówię, żebym na tym polegał, ale „mieszanie się” wydaje się niedokładne.Znalazłem świetną odpowiedź w podobnym pytaniu, które odwołuje się do oficjalnej dokumentacji. Cytując to:
Dla
Enumerable
metod (LINQ do obiektów, których dotyczyList<T>
), można polegać na zlecenie elementów zwróconych przezSelect
,Where
lubGroupBy
. Nie dotyczy to rzeczy z natury nieuporządkowanych, takich jakToDictionary
lubDistinct
.Niekoniecznie dotyczy to
IQueryable
metod rozszerzenia (inni dostawcy LINQ).Źródło: Czy wyliczalne metody LINQ utrzymują względną kolejność elementów?
źródło
Każda „grupa według” lub „kolejność według” prawdopodobnie zmieni kolejność.
źródło
Pytanie tutaj odnosi się konkretnie do LINQ-to-Objects.
Jeśli zamiast tego używasz LINQ-to-SQL, nie ma tam żadnego zamówienia, chyba że narzucisz taki z czymś takim jak:
Jeśli nie zrobisz tego z LINQ-to-SQL, kolejność wyników może się różnić między kolejnymi zapytaniami, nawet tych samych danych, co może powodować przejściowy błąd.
źródło