Eu tenho uma matriz de hashes:
[
{ :foo => 'foo', :bar => 2 },
{ :foo => 'foo', :bar => 3 },
{ :foo => 'foo', :bar => 5 },
]
Estou tentando classificar essa matriz em ordem decrescente de acordo com o valor de :bar
cada hash.
Estou usando sort_by
para classificar acima da matriz:
a.sort_by { |h| h[:bar] }
No entanto, isso classifica a matriz em ordem crescente. Como faço para classificar em ordem decrescente?
Uma solução era fazer o seguinte:
a.sort_by { |h| -h[:bar] }
Mas esse sinal negativo não parece apropriado.
sort_by.reverse
é dramaticamente mais eficiente do que a resposta atualmente aceita. Acredito que ele também lida melhor com a preocupação que você mencionou acima em "transmitir a intenção do código". Além disso, o homem de lata atualizou sua resposta para a versão atual do ruby. Esta pergunta foi vista mais de 15 mil vezes. Se você pode economizar até 1 segundo do tempo de cada espectador, acho que vale a pena.Respostas:
É sempre esclarecedor fazer uma referência nas várias respostas sugeridas. Aqui está o que eu descobri:
Acho interessante que o @ Pablo's
sort_by{...}.reverse!
seja o mais rápido. Antes de executar o teste, pensei que seria "-a[:bar]
" mais lento que " ", mas negar o valor leva mais tempo do que o necessário para reverter toda a matriz de uma só vez. Não faz muita diferença, mas cada pequena aceleração ajuda.Aqui estão os resultados para Ruby 1.9.3p194 (revisão em 20/04/2012 35410) [x86_64-darwin10.8.0]:
Estes estão em um MacBook Pro antigo. Máquinas mais novas ou mais rápidas terão valores mais baixos, mas as diferenças relativas permanecerão.
Aqui está uma versão um pouco atualizada no hardware mais recente e na versão 2.1.1 do Ruby:
Novos resultados executando o código acima usando o Ruby 2.2.1 em um Macbook Pro mais recente. Novamente, os números exatos não são importantes, são os relacionamentos deles:
Atualizado para Ruby 2.7.1 em um MacBook Pro de meados de 2015:
A fonte para
Array#reverse
é:do *p2-- = *p1++; while (--len > 0);
está copiando os ponteiros para os elementos na ordem inversa, se eu me lembrar corretamente do meu C, para que a matriz seja invertida.fonte
Apenas uma coisa rápida, que denota a intenção de ordem decrescente.
(Pensará em uma maneira melhor nesse meio tempo);)
fonte
Você poderia fazer:
fonte
sort_by
foi que ele evitado executando a função de comparação tantas vezessort_by
é muito mais eficiente e mais legível. Negar o valor ou fazer uma reversão no final será mais rápido e mais legível.* -1
não funciona com todos os valores (por exemplo, Tempo) ereverse
reordenará os valores classificados como iguaisVejo que temos (ao lado de outros) basicamente duas opções:
e
Embora os dois modos ofereçam o mesmo resultado quando sua chave de classificação é única, lembre-se de que o
reverse
caminho reverterá a ordem das chaves iguais .Exemplo:
Embora muitas vezes você não precise se preocupar com isso, às vezes precisa. Para evitar esse comportamento, você pode introduzir uma segunda chave de classificação (que com certeza precisa ser exclusiva, pelo menos para todos os itens que possuem a mesma chave de classificação):
fonte
reverse
é diferente. Eu acredito que ele também irá atrapalhar uma classificação anterior, no caso em que alguém está tentando aplicar várias classificações em alguma ordem.A respeito:
Funciona!!
fonte
sort
funcione, é mais rápido ao classificar valores imediatos. Se você tem que cavar para elessort_by
é mais rápido. Veja a referência.Em relação ao conjunto de benchmarks mencionado, esses resultados também são válidos para matrizes ordenadas.
sort_by
/reverse
é:E os resultados:
fonte
A solução simples de ascendente a descendente e vice-versa é:
CORDAS
DÍGITOS
fonte
Para quem gosta de medir a velocidade no IPS;)
E resultados:
fonte