tutorial examples español ejemplos create c# arrays linq sorting data-structures

c# - examples - Conservando el orden con LINQ



linq c# tutorial español (5)

¿De verdad estás hablando de SQL, o de arreglos? Para decirlo de otra manera, ¿estás usando LINQ to SQL o LINQ to Objects?

Los operadores de LINQ to Objects no cambian realmente su origen de datos original, sino que crean secuencias que están respaldadas por el origen de datos. Las únicas operaciones que cambian el orden son OrderBy / OrderByDescending / ThenBy / ThenByDescending - e incluso entonces, 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 se convierte a una estructura de datos diferente, por ejemplo, con ToLookup o ToDictionary, no creo que el orden se conserve en ese punto, pero eso es algo diferente de todos modos. (Aunque creo que el orden de los valores que se asignan a la misma clave se conserva para las búsquedas).

Utilizo instrucciones de LINQ to Objects en una matriz ordenada. ¿Qué operaciones no debería hacer para asegurarme de que el orden de la matriz no cambia?


Cualquier ''agrupar por'' o ''ordenar por'' posiblemente cambiará el pedido.


Encontré una gran respuesta en una pregunta similar que hace referencia a la documentación oficial. Para citarlo:

Para los métodos Enumerable (LINQ to Objects, que se aplican a la List<T> ), puede confiar en el orden de los elementos devueltos por Select , Where o GroupBy . Este no es el caso de cosas que están intrínsecamente desordenadas como ToDictionary o Distinct .

De la documentación de Enumerable.GroupBy :

Los IGrouping<TKey, TElement> se muestran en un orden basado en el orden de los elementos en la fuente que produjo la primera clave de cada IGrouping<TKey, TElement> . Los elementos de una agrupación se muestran en el orden en que aparecen en la source .

Esto no es necesariamente cierto para los métodos de extensión IQueryable (otros proveedores de LINQ).

Fuente: ¿Los métodos enumerables de LINQ mantienen el orden relativo de los elementos?


Examiné los métodos de System.Linq.Enumerable , descartando cualquiera que devolviera resultados no IEnumerables. Revisé los comentarios de cada uno para determinar cómo el orden del resultado diferiría del orden de la fuente.

Conserva Orden Absolutamente. Puede asignar un elemento de origen por índice a un elemento de resultado

  • ComoEnumerable
  • Emitir
  • Concat
  • Seleccionar
  • ToArray
  • Listar

Conserva la Orden. Los elementos se filtran, pero no se reordenan.

  • Distinto
  • Excepto
  • Intersecarse
  • De tipo
  • Omitir
  • SkipWhile
  • Tomar
  • TakeWhile
  • Dónde
  • Zip (nuevo en .net 4)

Destruye el orden: no sabemos en qué orden esperar resultados.

  • Al diccionario
  • Para buscar

Redefine el pedido explícitamente - use estos para cambiar el orden del resultado

  • Orden por
  • OrderByDescending
  • Marcha atrás
  • Entonces por
  • ThenByDescending

Redefine el orden de acuerdo a algunas reglas.

  • GroupBy: los objetos de IGrouping se generan en un orden basado en el orden de los elementos en la fuente que produjo la primera clave de cada IGrouping. Los elementos de una agrupación se muestran en el orden en que aparecen en la fuente.
  • GroupJoin - GroupJoin conserva el orden de los elementos de exterior, y para cada elemento de externo, el orden de los elementos coincidentes de interno.
  • Unir: conserva el orden de los elementos de exterior y, para cada uno de estos elementos, el orden de los elementos de coincidencia de interno.
  • SelectMany: para cada elemento de la fuente, se invoca el selector y se devuelve una secuencia de valores.
  • Unión: cuando se enumera el objeto devuelto por este método, Unión enumera primero y segundo en ese orden y produce cada elemento que aún no se ha producido.

Edición: He movido Distinct to Preserving order basado en esta implementation .

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; }


Si está trabajando en una matriz, parece que está usando LINQ-to-Objects, no SQL; ¿puedes confirmar? La mayoría de las operaciones LINQ no reordenan nada (la salida estará en el mismo orden que la entrada), así que no aplique otro tipo (OrderBy [Descendente] / ThenBy [Descendente]).

[editar: como Jon puso más claramente; LINQ generalmente crea una nueva secuencia, dejando solo los datos originales]

Tenga en cuenta que insertar los datos en un Dictionary<,> (ToDictionary) mezclará 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, Omitir, Tomar) deberían estar bien.