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é?
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é?
Réponses:
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'il Distinct
appartient à la catégorie de filtrage ci-dessus, tout comme Where
.
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.)
GroupBy
suivi SelectMany
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.
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 applique List<T>
), vous pouvez compter sur l'ordre des éléments retournés par Select
, Where
ou GroupBy
. Ce n'est pas le cas pour les choses qui sont intrinsèquement non ordonnées comme ToDictionary
ou Distinct
.
De la documentation Enumerable.GroupBy :
Les
IGrouping<TKey, TElement>
objets sont livrés dans un ordre basé sur l'ordre des éléments en source qui ont produit la première clé de chacunIGrouping<TKey, TElement>
. Les éléments d'un regroupement sont générés dans l'ordre dans lequel ils apparaissentsource
.
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 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:
mysqlresult.OrderBy(e=>e.SomeColumn)
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.