从数组创建哈希的最简洁方法

Dan*_*ley 28 ruby arrays hash ruby-on-rails

我似乎经常遇到这种情况.我需要使用数组中每个对象的属性作为键从数组构建一个Hash.

让我们说我需要一个哈希的例子使用ActiveRecord objecs键入他们的ID共同的方式:

ary = [collection of ActiveRecord objects]
hash = ary.inject({}) {|hash, obj| hash[obj.id] = obj }
Run Code Online (Sandbox Code Playgroud)

其他方式:

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

Dream Way:我可以并且可能自己创建这个,但是Ruby或Rails中有什么东西会这样吗?

ary = [collection of ActiveRecord objects]
hash = ary.to_hash &:id
#or at least
hash = ary.to_hash {|obj| obj.id}
Run Code Online (Sandbox Code Playgroud)

Aug*_*aas 57

ActiveSupport中已有一种方法可以做到这一点.

['an array', 'of active record', 'objects'].index_by(&:id)
Run Code Online (Sandbox Code Playgroud)

只是为了记录,这是实施:

def index_by
  inject({}) do |accum, elem|
    accum[yield(elem)] = elem
    accum
  end
end
Run Code Online (Sandbox Code Playgroud)

哪些可以被重构(如果你迫切需要单行):

def index_by
  inject({}) {|hash, elem| hash.merge!(yield(elem) => elem) }
end
Run Code Online (Sandbox Code Playgroud)

  • group_by有一个数组作为值,而index_by假设每个键只有一个项目,因此值是单个项目,而不是数组. (2认同)

zed*_*xff 9

最短的一个?

# '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
Run Code Online (Sandbox Code Playgroud)


Fed*_*omp 7

如果有人得到普通阵列

arr = ["banana", "apple"]
Hash[arr.map.with_index.to_a]
 => {"banana"=>0, "apple"=>1}
Run Code Online (Sandbox Code Playgroud)


ewa*_*she 5

您可以自己将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
Run Code Online (Sandbox Code Playgroud)