Como classificar uma matriz de hashes em ruby

147

Eu tenho uma matriz, cada um de cujos elementos é um hash com três pares de chave / valor:

:phone => "2130001111", :zip => "12345", :city => "sometown"

Eu gostaria de classificar os dados zippara que todos os phones na mesma área estejam juntos. Ruby tem uma maneira fácil de fazer isso? Pode will_paginatepaginar dados em uma matriz?

jpw
fonte
Se você estiver gerando a matriz, em vez de ser um dado, considere torná-la um hash, com elementos (por exemplo) [city,zip]=>phoneou city=>{zip1=>[<phones>], zip2=>...}.
Cary Swoveland

Respostas:

364

Simples:

array_of_hashes.sort_by { |hsh| hsh[:zip] }

Nota:

Ao usar, sort_byé necessário atribuir o resultado a uma nova variável: array_of_hashes = array_of_hashes.sort_by{}caso contrário, você pode usar o método "bang" para modificar no local:array_of_hashes.sort_by!{}

Gareth
fonte
8
Ao usar, sort_byé necessário atribuir o resultado a uma nova variável: array_of_hashes = array_of_hashes.sort_by{}caso contrário, você pode usar o método "bang" para modificar no local:array_of_hashes.sort_by!{}
Andrew
11
Ainda mais curto:array_of_hashes.sort_by(&:zip)
Etienne
24
@ Etienne: Esse é um atalho para .sort_by { |hsh| hsh.zip }e, portanto, só funcionará se .zipfor definido como um método em cada Hash. Por padrão, os hashes não expõem suas chaves como métodos, então acho que você provavelmente tem algo mais acontecendo lá.
Gareth
Observe o estrondo:array_of_hashes.sort_by!(&:zip)
Diego D
@ Gareth: No caso de ActiveRecords, .zipe [:zip]ambos funcionarão. Os ActiveRecords têm ambos os estilos definidos.
Atul Vaibhav 27/06
17
sorted = dataarray.sort {|a,b| a[:zip] <=> b[:zip]}
Edu
fonte
10

Use o bang para modificar no local a matriz:

array_of_hashes.sort_by!(&:zip)

Ou redesigne-o:

array_of_hashes = array_of_hashes.sort_by(&:zip)

Observe que o método sort_by classifica por ordem crescente.

Se você precisar classificar em ordem decrescente, poderá fazer algo assim:

array_of_hashes.sort_by!(&:zip).reverse!

ou

array_of_hashes = array_of_hashes.sort_by(&:zip).reverse
Diego D
fonte
6
A notação &:é um atalho para method, não attribute! Você está presumindo que o Hash tem métodos que refletem atributos ..
Andre Figueiredo
1
Obrigado pelo reversemétodo: p
Alain ANDRE 2/17
4

Se você quiser paginar os dados na matriz, deverá exigir 'will_paginate / array' em seu controlador

taivn07
fonte
2

Se você possui Hash aninhado (Hash dentro de um formato de hash) como elementos de matriz (uma estrutura como a seguinte) e deseja classificá-lo por chave (data aqui)

data =  [
    {
        "2018-11-13": {
            "avg_score": 4,
            "avg_duration": 29.24
        }
    },
    {
         "2017-03-13": {
            "avg_score": 4,
            "avg_duration": 40.24
        }
    },
    {
         "2018-03-13": {
            "avg_score": 4,
            "avg_duration": 39.24
        }
    }
]

Use o método Array 'sort_by' como

data.sort_by { |element| element.keys.first }
Abhi
fonte