Самый чистый способ создать хэш из массива - PullRequest
28 голосов
/ 05 января 2009

Кажется, я сталкиваюсь с этим очень часто. Мне нужно построить Hash из массива, используя атрибут каждого объекта в массиве в качестве ключа.

Допустим, мне нужен хэш примера использования объектов ActiveRecord, основанных на их идентификаторах. Общий способ:

ary = [collection of ActiveRecord objects]
hash = ary.inject({}) {|hash, obj| hash[obj.id] = obj }

Другой способ:

ary = [collection of ActiveRecord objects]
hash = Hash[*(ary.map {|obj| [obj.id, obj]}).flatten]

Путь мечты: Я мог и мог бы создать это сам, но есть ли что-нибудь в Ruby или Rails, которое это сделает?

ary = [collection of ActiveRecord objects]
hash = ary.to_hash &:id
#or at least
hash = ary.to_hash {|obj| obj.id}

Ответы [ 5 ]

56 голосов
/ 05 января 2009

В ActiveSupport уже есть метод, который делает это.

['an array', 'of active record', 'objects'].index_by(&:id)

И просто для записи, вот реализация:

def index_by
  inject({}) do |accum, elem|
    accum[yield(elem)] = elem
    accum
  end
end

Который мог быть реорганизован (если вы отчаянно нуждаетесь в однострочниках):

def index_by
  inject({}) {|hash, elem| hash.merge!(yield(elem) => elem) }
end
9 голосов
/ 15 апреля 2013

самый короткий?

# 'Region' is a sample class here
# you can put 'self.to_hash' method into any class you like 

class Region < ActiveRecord::Base
  def self.to_hash
    Hash[*all.map{ |x| [x.id, x] }.flatten]
  end
end
7 голосов
/ 10 марта 2017

В случае, если кто-то получил простой массив

arr = ["banana", "apple"]
Hash[arr.map.with_index.to_a]
 => {"banana"=>0, "apple"=>1}
5 голосов
/ 05 января 2009

Вы можете добавить to_hash в Array самостоятельно.

class Array
  def to_hash(&block)
    Hash[*self.map {|e| [block.call(e), e] }.flatten]
  end
end

ary = [collection of ActiveRecord objects]
ary.to_hash do |element|
  element.id
end
0 голосов
/ 05 января 2009

Установите Ruby Facets Gem и используйте их Array.to_h .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...