Сортировка хэша хэшей по значению (и возвращение хэша, а не массива) - PullRequest
11 голосов
/ 12 июня 2009

У меня есть следующий хэш:

user = {
  'user' => {
    'title' => {'weight' => 1, .... }
    'body' => {'weight' => 4, ....}
     ....
     ....
  }
}

Можно ли отсортировать пользователя по ключу веса его дочерних хешей?

Я посмотрел в Hash.sort, но похоже, что он возвращает массив, а не мой отсортированный хэш.

Ответы [ 2 ]

11 голосов
/ 12 июня 2009

В Ruby 1.9 Hash сортируются, но Hash#sort по-прежнему возвращает Array из Array с. Представь это! Это означает, что вы можете создать свой собственный метод сортировки поверх него.

class Hash
  def sorted_hash(&block)
    self.class[sort(&block)]   # Hash[ [[key1, value1], [key2, value2]] ]
  end
end

Hash в Ruby 1.8 не отсортированы. Если вам нужна совместимость с Ruby 1.8, вы можете использовать ActiveSupport OrderedHash. Он ведет себя как 1.9- Hash, поэтому вы можете определить для него тот же метод sorted_hash:

class ActiveSupport::OrderedHash
  def sorted_hash(&block)
    self.class[sort(&block)]
  end
end

hash = ActiveSupport::OrderedHash.new
hash["b"] = "b"
hash["a"] = "a"
hash               #=> {"b"=>"b", "a"=>"a"}  => unsorted
hash.sorted_hash   #=> {"a"=>"a", "b"=>"b"}  => sorted!

Вы должны скопировать метод sorted_hash в свой код, потому что он не существует по умолчанию!

Обновление для глубокой сортировки: Если вы хотите отсортировать что-то еще, кроме ключа хеша, передайте блок методу sorted_hash следующим образом (при условии реализации сверху):

hash = ActiveSupport::OrderedHash.new
hash["a"] = { "attr" => "2", "..." => "..." }
hash["b"] = { "attr" => "1", "..." => "..." }

# Unsorted.
hash 
  #=> {"a"=>{"attr"=>"2", "..."=>"..."}, "b"=>{"attr"=>"1", "..."=>"..."}}

# Sort on the "attr" key. (Assuming every value is a Hash itself!)
hash.sorted_hash { |a, b| a[1]["attr"] <=> b[1]["attr"] }
  #=> {"b"=>{"attr"=>"1", "..."=>"..."}, "a"=>{"attr"=>"2", "..."=>"..."}}
8 голосов
/ 12 июня 2009

Хэши - это принципиально несортированные структуры данных; Hash#sort действительно то, что вы хотите. Либо так, либо сортируйте список ключей, а затем используйте его, чтобы перечислять, когда пришло время выводить хеш, вместо того, чтобы перечислять непосредственно по хешу, используя свои собственные методы.

...