Eu uso instruções LINQ to Objects em uma matriz ordenada. Quais operações não devo executar para garantir que a ordem da matriz não seja alterada?
361
Examinei os métodos de System.Linq.Enumerable , descartando qualquer que retornasse resultados não IEnumerable. Verifiquei as observações de cada um para determinar como a ordem do resultado seria diferente da ordem da fonte.
Preserva a ordem absolutamente. Você pode mapear um elemento de origem por índice para um elemento de resultado
Preserva a ordem. Os elementos são filtrados ou adicionados, mas não são reordenados.
Destrói a ordem - não sabemos em que ordem esperar resultados.
Redefine o pedido explicitamente - use-os para alterar a ordem do resultado
Redefine o pedido de acordo com algumas regras.
Editar: movi a ordem Distinct para Preserving com base nessa implementação .
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) tenha apenas a intenção de dizer "não classificado", não "em ordem imprevisível". Eu diria queDistinct
pertence à categoria de filtragem acima, assim comoWhere
.Você está realmente falando sobre SQL ou sobre matrizes? Em outras palavras, você está usando o LINQ to SQL ou o LINQ to Objects?
Na verdade, os operadores LINQ to Objects não alteram sua fonte de dados original - eles constroem sequências efetivamente apoiadas pela fonte de dados. As únicas operações que alteram a ordem são OrderBy / OrderByDescending / ThenBy / ThenByDescending - e, mesmo assim, são estáveis para elementos igualmente ordenados. Obviamente, muitas operações filtrarão alguns elementos, mas os elementos retornados estarão na mesma ordem.
Se você converter para uma estrutura de dados diferente, por exemplo, com ToLookup ou ToDictionary, não acredito que a ordem seja preservada nesse momento - mas, de qualquer maneira, isso é um pouco diferente. (A ordem dos valores mapeados para a mesma chave é preservada para pesquisas, acredito.)
fonte
GroupBy
seguido porSelectMany
fornecerá os resultados agrupados por chave, mas não em ordem crescente de chave ... ele os fornecerá na ordem em que as chaves ocorreram originalmente.list<x> {a b c d e f g}
se c, d, e tiverem a mesma chave, a sequência resultante conterá c, d, e próximos um do outro E na ordem c, d, e. Não consigo encontrar uma resposta categórica baseada em MS.Se você estiver trabalhando em uma matriz, parece que você está usando LINQ-to-Objects, não SQL; Você pode confirmar? A maioria das operações do LINQ não reordena nada (a saída será na mesma ordem que a entrada) - portanto, não aplique outra classificação (OrderBy [Descending] / ThenBy [Descending]).
[editar: como Jon colocou mais claramente; O LINQ geralmente cria uma nova sequência, deixando os dados originais em paz.
Observe que inserir os dados em um
Dictionary<,>
(ToDictionary) embaralha os dados, pois o dicionário não respeita nenhuma ordem de classificação específica.Mas as coisas mais comuns (Selecionar, Onde, Pular, Tomar) devem ficar bem.
fonte
ToDictionary()
simplesmente não faz promessas sobre a ordem, mas, na prática, mantém a ordem de entrada (até você remover algo dela). Não estou dizendo para confiar nisso, mas 'embaralhar' parece impreciso.Encontrei uma ótima resposta em uma pergunta semelhante que faz referência à documentação oficial. Para citar:
Para
Enumerable
métodos (LINQ to Objects, que se aplica aList<T>
), você pode contar com a ordem dos elementos retornados porSelect
,Where
ouGroupBy
. Este não é o caso de coisas que são inerentemente não ordenadas, comoToDictionary
ouDistinct
.Isso não é necessariamente verdadeiro para
IQueryable
métodos de extensão (outros provedores LINQ).Fonte: Os métodos enumeráveis do LINQ mantêm a ordem relativa dos elementos?
fonte
Qualquer 'agrupar por' ou 'ordenar por' possivelmente mudará a ordem.
fonte
A questão aqui se refere especificamente a LINQ-to-Objects.
Se você estiver usando o LINQ-to-SQL, não há pedido, a menos que você imponha um com algo como:
Se você não fizer isso com o LINQ-to-SQL, a ordem dos resultados poderá variar entre as consultas subseqüentes, mesmo os mesmos dados, o que pode causar um erro intermitente.
fonte