Uso las instrucciones de LINQ to Objects en una matriz ordenada. ¿Qué operaciones no debo hacer para asegurarme de que no se cambie el orden de la matriz?
Uso las instrucciones de LINQ to Objects en una matriz ordenada. ¿Qué operaciones no debo hacer para asegurarme de que no se cambie el orden de la matriz?
Respuestas:
Examiné los métodos de System.Linq.Enumerable , descartando cualquiera que arrojara resultados no IEnumerable. Revisé los comentarios de cada uno para determinar cómo el orden del resultado diferiría del orden de la fuente.
Preserva el orden absolutamente. Puede asignar un elemento fuente por índice a un elemento resultado
Preserva el orden. Los elementos se filtran o agregan, pero no se reordenan.
Destruye el orden: no sabemos en qué orden esperar resultados.
Redefine el orden explícitamente: utilícelos para cambiar el orden del resultado
Redefine el orden de acuerdo con algunas reglas.
Editar: He movido Distinct a Preserve order basado en esta implementación .
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étodo) solo significaba "sin clasificar", no "en orden impredecible". Yo diría que Distinct
pertenece a la categoría de filtrado anterior, al igual que Where
.
¿Estás hablando realmente de SQL o de matrices? Para decirlo de otra manera, ¿estás usando LINQ to SQL o LINQ to Objects?
Los operadores de LINQ to Objects en realidad no cambian su fuente de datos original: construyen secuencias que están respaldadas efectivamente por la fuente de datos. Las únicas operaciones que cambian el orden son OrderBy / OrderByDescending / ThenBy / ThenByDescending, y aun así, son estables para elementos igualmente ordenados. Por supuesto, muchas operaciones filtrarán algunos elementos, pero los elementos que se devuelven estarán en el mismo orden.
Si convierte a una estructura de datos diferente, por ejemplo, con ToLookup o ToDictionary, no creo que se mantenga el orden en ese punto, pero de todos modos eso es algo diferente. (Creo que el orden de asignación de valores a la misma clave se conserva para las búsquedas).
GroupBy
seguido de SelectMany
dará los resultados agrupados por clave, pero no en orden ascendente de la clave ... los dará en el orden en que ocurrieron las claves originalmente.
list<x> {a b c d e f g}
si c, d, e tienen la misma clave, la secuencia resultante contendrá c, d, e una al lado de la otra Y en el orden c, d, e. Parece que no puedo encontrar una respuesta categórica basada en MS.
Si está trabajando en una matriz, parece que está utilizando LINQ-to-Objects, no SQL; ¿puedes confirmar? La mayoría de las operaciones de LINQ no reordenan nada (la salida estará en el mismo orden que la entrada), así que no aplique otro tipo (OrderBy [Descending] / ThenBy [Descending]).
[editar: como Jon puso más claramente; LINQ generalmente crea una nueva secuencia, dejando solo los datos originales]
Tenga en cuenta que Dictionary<,>
insertar los datos en un (ToDictionary) codificará los datos, ya que el diccionario no respeta ningún orden de clasificación en particular.
Pero las cosas más comunes (Seleccionar, Dónde, Saltar, Tomar) deberían estar bien.
ToDictionary()
simplemente no hace promesas sobre el orden, sino que en la práctica mantiene el orden de entrada (hasta que elimine algo de él). No estoy diciendo que confíe en esto, pero 'revolver' parece inexacto.
Encontré una gran respuesta en una pregunta similar que hace referencia a la documentación oficial. Para citarlo:
Para Enumerable
métodos (LINQ a objetos, que se aplica a List<T>
), se puede confiar en el orden de los elementos devueltos por Select
, Where
o GroupBy
. Este no es el caso para cosas que son inherentemente desordenadas como ToDictionary
o Distinct
.
De la documentación de Enumerable.GroupBy :
Los
IGrouping<TKey, TElement>
objetos se entregan en un orden basado en el orden de los elementos en origen que produjeron la primera clave de cada unoIGrouping<TKey, TElement>
. Los elementos de una agrupación se obtienen en el orden en que aparecensource
.
Esto no es necesariamente cierto para los IQueryable
métodos de extensión (otros proveedores de LINQ).
Fuente: ¿Los métodos enumerables de LINQ mantienen el orden relativo de los elementos?
La pregunta aquí se refiere específicamente a LINQ-to-Objects.
Si usa LINQ-to-SQL en su lugar, no hay orden allí a menos que imponga uno con algo como:
mysqlresult.OrderBy(e=>e.SomeColumn)
Si no hace esto con LINQ-to-SQL, el orden de los resultados puede variar entre consultas posteriores, incluso de los mismos datos, lo que podría causar un error intermitente.