J'utilise les instructions LINQ to Objects sur un tableau ordonné. Quelles opérations ne dois-je pas faire pour être sûr que l'ordre du tableau n'est pas modifié?
361
J'ai examiné les méthodes de System.Linq.Enumerable , en rejetant toutes celles qui renvoyaient des résultats non IEnumerable. J'ai vérifié les remarques de chacun pour déterminer en quoi l'ordre du résultat différerait de l'ordre de la source.
Préserve l'ordre absolument. Vous pouvez mapper un élément source par index à un élément de résultat
Préserve l'ordre. Les éléments sont filtrés ou ajoutés, mais pas réorganisés.
Détruit l'ordre - nous ne savons pas dans quel ordre s'attendre.
Redéfinit explicitement l'ordre - utilisez-les pour modifier l'ordre du résultat
Redéfinit l'ordre selon certaines règles.
Edit: J'ai déplacé Distinct à l'ordre de conservation basé sur cette implémentation .
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
méthode) voulait juste dire "non trié", pas "dans un ordre imprévisible". Je dirais qu'ilDistinct
appartient à la catégorie de filtrage ci-dessus, tout commeWhere
.Parlez-vous réellement de SQL ou de tableaux? En d'autres termes, utilisez-vous LINQ to SQL ou LINQ to Objects?
Les opérateurs LINQ to Objects ne changent pas réellement leur source de données d'origine - ils construisent des séquences qui sont efficacement soutenues par la source de données. Les seules opérations qui modifient l'ordre sont OrderBy / OrderByDescending / ThenBy / ThenByDescending - et même alors, celles-ci sont stables pour des éléments également ordonnés. Bien sûr, de nombreuses opérations filtreront certains éléments, mais les éléments renvoyés seront dans le même ordre.
Si vous convertissez vers une structure de données différente, par exemple avec ToLookup ou ToDictionary, je ne crois pas que l'ordre soit préservé à ce stade - mais c'est quelque peu différent de toute façon. (L'ordre des valeurs mappées à la même clé est cependant conservé pour les recherches, je crois.)
la source
GroupBy
suiviSelectMany
donnera les résultats regroupés par clé, mais pas dans l'ordre croissant des clés ... il les donnera dans l'ordre dans lequel les clés se sont produites à l'origine.list<x> {a b c d e f g}
si c, d, e ont tous la même clé, alors la séquence résultante contiendra c, d, e côte à côte ET dans l'ordre c, d, e. Je n'arrive pas à trouver une réponse catégorique basée sur MS.Si vous travaillez sur un tableau, il semble que vous utilisez LINQ-to-Objects, pas SQL; pouvez-vous confirmer? La plupart des opérations LINQ ne réordonnent rien (la sortie sera dans le même ordre que l'entrée) - donc n'appliquez pas un autre tri (OrderBy [Descending] / ThenBy [Descending]).
[modifier: comme Jon l'a dit plus clairement; LINQ crée généralement une nouvelle séquence, laissant les données originales seules]
Notez que pousser les données dans un
Dictionary<,>
(ToDictionary) brouillera les données, car le dictionnaire ne respecte aucun ordre de tri particulier.Mais les choses les plus courantes (sélectionner, où, sauter, prendre) devraient convenir.
la source
ToDictionary()
ne fait simplement aucune promesse sur la commande, mais dans la pratique, maintient l'ordre d'entrée (jusqu'à ce que vous en supprimiez quelque chose). Je ne dis pas de me fier à cela, mais «brouiller» semble inexact.J'ai trouvé une excellente réponse dans une question similaire qui fait référence à la documentation officielle. Pour le citer:
Pour les
Enumerable
méthodes (LINQ to Objects, qui appliqueList<T>
), vous pouvez compter sur l'ordre des éléments retournés parSelect
,Where
ouGroupBy
. Ce n'est pas le cas pour les choses qui sont intrinsèquement non ordonnées commeToDictionary
ouDistinct
.Ce n'est pas nécessairement vrai pour les
IQueryable
méthodes d'extension (autres fournisseurs LINQ).Source: Les méthodes énumérables de LINQ maintiennent-elles l'ordre relatif des éléments?
la source
Tout «groupé par» ou «commandé par» modifiera éventuellement la commande.
la source
La question ici se réfère spécifiquement à LINQ-to-Objects.
Si vous utilisez LINQ-to-SQL à la place, il n'y a pas d'ordre, sauf si vous en imposez un avec quelque chose comme:
Si vous ne le faites pas avec LINQ-to-SQL, l'ordre des résultats peut varier entre les requêtes suivantes, même des mêmes données, ce qui pourrait provoquer un bogue intermittent.
la source