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?
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?
Respostas:
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 que Distinct
pertence à categoria de filtragem acima, assim como Where
.
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.)
GroupBy
seguido por SelectMany
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.
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 a List<T>
), você pode contar com a ordem dos elementos retornados por Select
, Where
ou GroupBy
. Este não é o caso de coisas que são inerentemente não ordenadas, como ToDictionary
ou Distinct
.
Da documentação Enumerable.GroupBy :
Os
IGrouping<TKey, TElement>
objetos são produzidos em uma ordem com base na ordem dos elementos na origem que produziram a primeira chave de cada umIGrouping<TKey, TElement>
. Os elementos de um agrupamento são gerados na ordem em que aparecemsource
.
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?
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:
mysqlresult.OrderBy(e=>e.SomeColumn)
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.