Uso le istruzioni LINQ to Objects su un array ordinato. Quali operazioni non dovrei fare per essere sicuro che l'ordine dell'array non sia cambiato?
Uso le istruzioni LINQ to Objects su un array ordinato. Quali operazioni non dovrei fare per essere sicuro che l'ordine dell'array non sia cambiato?
Risposte:
Ho esaminato i metodi di System.Linq.Enumerable , scartando quelli che restituivano risultati non IEnumerable. Ho controllato le osservazioni di ciascuno per determinare in che modo l'ordine del risultato differirebbe dall'ordine della fonte.
Conserva l'ordine assolutamente. È possibile mappare un elemento sorgente per indice a un elemento risultato
Conserva l'ordine. Gli elementi vengono filtrati o aggiunti, ma non riordinati.
Distrugge l'ordine: non sappiamo in quale ordine aspettarsi i risultati.
Ridefinisce l'ordine esplicitamente: utilizzare questi per modificare l'ordine del risultato
Ridefinisce l'ordine secondo alcune regole.
Modifica: ho spostato Distinto in Ordine di conservazione in base a questa implementazione .
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
metodo) significava solo "non ordinata", non "in ordine imprevedibile". Direi che Distinct
appartiene alla categoria di filtro sopra, proprio come Where
.
In realtà stai parlando di SQL o di array? Per dirla in altro modo, stai usando LINQ to SQL o LINQ to Objects?
Gli operatori LINQ to Objects in realtà non modificano l'origine dati originale, ma creano sequenze che sono effettivamente supportate dall'origine dati. Le uniche operazioni che modificano l'ordinamento sono OrderBy / OrderByDescending / ThenBy / ThenByDescending - e anche in questo caso, sono stabili per gli elementi equamente ordinati. Naturalmente, molte operazioni filtrano alcuni elementi, ma gli elementi che vengono restituiti saranno nello stesso ordine.
Se ti converti in una diversa struttura di dati, ad esempio con ToLookup o ToDictionary, non credo che l'ordine venga conservato a quel punto, ma è comunque leggermente diverso. (Credo che l'ordine dei valori associati alla stessa chiave sia conservato per le ricerche).
GroupBy
seguito da SelectMany
darà i risultati raggruppati per chiave, ma non in ordine crescente di chiave ... li darà nell'ordine in cui le chiavi si sono originariamente verificate.
list<x> {a b c d e f g}
se c, d, e hanno tutti la stessa chiave, la sequenza risultante conterrà c, d, e uno accanto all'altro E nell'ordine c, d, e. Non riesco a trovare una risposta categorica basata sulla SM.
Se stai lavorando su un array, sembra che tu stia usando LINQ-to-Objects, non SQL; Puoi confermare? La maggior parte delle operazioni LINQ non riordina nulla (l'output sarà nello stesso ordine dell'input) - quindi non applicare un altro ordinamento (OrderBy [Descending] / ThenBy [Descending]).
[modifica: come Jon ha messo più chiaramente; LINQ generalmente crea una nuova sequenza, lasciando da soli i dati originali]
Notare che spingendo i dati in un Dictionary<,>
(ToDictionary) si mescolano i dati, poiché il dizionario non rispetta alcun particolare ordinamento.
Ma le cose più comuni (Seleziona, Dove, Salta, Prendi) dovrebbero andare bene.
ToDictionary()
semplicemente promesse sull'ordine, ma in pratica mantiene l'ordine di input (fino a quando non rimuovi qualcosa da esso). Non sto dicendo di fare affidamento su questo, ma "rimescolare" sembra impreciso.
Ho trovato un'ottima risposta in una domanda simile che fa riferimento alla documentazione ufficiale. Per citarlo:
Per Enumerable
i metodi (LINQ to Objects, che si applica a List<T>
), si può contare su l'ordine degli elementi restituiti da Select
, Where
o GroupBy
. Questo non è il caso di cose intrinsecamente non ordinate come ToDictionary
o Distinct
.
Da Enumerable.GroupBy documentazione di :
Gli
IGrouping<TKey, TElement>
oggetti vengono generati in un ordine basato sull'ordine degli elementi in sorgente che hanno prodotto la prima chiave di ciascunoIGrouping<TKey, TElement>
. Gli elementi in un raggruppamento vengono prodotti nell'ordine in cui appaionosource
.
Questo non è necessariamente vero per i IQueryable
metodi di estensione (altri provider LINQ).
Fonte: i metodi enumerabili di LINQ mantengono l'ordine relativo degli elementi?
La domanda qui si riferisce specificamente a LINQ-to-Objects.
Se si utilizza LINQ-to-SQL invece non c'è alcun ordine a meno che non si imponga uno con qualcosa di simile:
mysqlresult.OrderBy(e=>e.SomeColumn)
Se non lo si fa con LINQ-to-SQL, l'ordine dei risultati può variare tra le query successive, anche degli stessi dati, che potrebbero causare un bug intermittente.