Preservar el orden con LINQ


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

Author: Machavity, 2008-10-15

5 answers

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

Conserva el Orden Absolutamente. Puede asignar un elemento source por índice a un elemento result

  • AsEnumerable
  • Cast
  • Concat
  • Seleccione
  • toArray
  • ToList

Conserva el Orden. Los elementos son filtrado, pero no reordenado.

  • Distinto
  • Excepto
  • Intersect
  • OfType
  • Skip
  • SkipWhile
  • Tome
  • takeWhile
  • Donde
  • Zip (nuevo en. net 4)

Destruye el Orden - no sabemos en qué orden esperar resultados.

  • ToDictionary
  • Buscar

Redefine el Orden Explícitamente-use estos para cambiar el orden de la resultado

  • OrderBy
  • OrderByDescending
  • Inverso
  • Luego
  • ThenByDescending

Redefine el Orden según algunas reglas.

  • GroupBy - Los objetos IGrouping se producen 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 preserva el orden de los elementos de outer, y para cada elemento de exterior, el orden de los elementos coincidentes de interior.
  • Join - conserva el orden de los elementos de outer, y para cada uno de estos elementos, el orden de los elementos coincidentes de inner.
  • SelectMany - para cada elemento de source, se invoca selector y se devuelve una secuencia de valores.
  • Union-Cuando se enumera el objeto devuelto por este método, Union enumera primero y segundo en ese orden y produce cada elemento que aún no ha sido ceder.

Editar: He movido Distinct a Preservar el orden 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;
    }
 546
Author: Amy B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-17 16:56:31

¿Estás hablando realmente de SQL, o de arrays? Para decirlo de otra manera, ¿está utilizando LINQ para SQL o LINQ para Objetos?

Los operadores LINQ to Objects en realidad no cambian su fuente de datos original - construyen secuencias que son efectivamente respaldadas por la fuente 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 se filtrarán algunos elementos, pero los elementos que se devuelven en el mismo orden.

Si 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. (Sin embargo, creo que el orden de los valores que se asignan a la misma clave se conserva para las búsquedas.)

 29
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-15 12:24:00

Si está trabajando en una matriz, parece que está utilizando LINQ-to-Objects, no SQL; ¿puede 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 de orden (OrderBy[Descending]/ThenBy[Descending]).

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

Tenga en cuenta que empujar los datos en un Dictionary<,> (ToDictionary) codificará los datos, como 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.

 6
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-15 12:25:09

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 aplica a List<T>), puede confiar en el orden de los elementos devueltos por Select, Where, o GroupBy. Este no es el caso de las cosas que están inherentemente desordenadas como ToDictionary o Distinct.

De Enumerable.GroupBy documentación:

Los objetos IGrouping<TKey, TElement> se producen en un orden basado en el orden de la elementos en source que produjeron la primera clave de cada IGrouping<TKey, TElement>. Los elementos de una agrupación se muestran en el orden en que aparecen en 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?

 3
Author: Curtis Yallop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:53

Cualquier 'group by' u 'order by' posiblemente cambiará el orden.

 2
Author: leppie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-15 12:53:11