3

我发现我经常使用迭代可枚举的方法以返回不同的可枚举或哈希。这些方法几乎总是看起来像这个简单的例子:

  def build_hash(array)
    hash = {}
    array.each do |item|
      hash[ item[:id] ]= item
    end
    hash
  end

这种方法很有效,但我经常想知道是否有更简洁的方法可以做到这一点,特别是不必将循环包装在临时对象中以便返回正确。

有谁知道改进和/或更清洁和/或更快的方法来做到这一点,或者这几乎是最好的方法?

4

5 回答 5

3

考虑到您的具体示例,这里有几种方法

arr = [{:id => 1, :name => :foo}, {:id => 2, :name => :bar}]

Hash[arr.map{ |o| [o[:id], o] }]
arr.each_with_object({}){ |o, h| h[o[:id]] = o }
arr.reduce({}){ |h, o| h[o[:id]] = o; h }
arr.reduce({}){ |h, o| h.merge o[:id] => o }

# each of these return the same Hash
# {1=>{:id=>1, :name=>:foo}, 2=>{:id=>2, :name=>:bar}} 
于 2013-03-01T19:27:21.223 回答
1

您可以使用 ActiveSupport 的index_by.

你的例子变得微不足道:

def build_hash(array)
  array.index_by{|item| item[:id]}
end

目前,即使在 Ruby 2.0 中,也没有在 Ruby 中构建散列的真正好方法。

你可以使用Hash[],虽然我觉得很丑:

def build_hash(array)
  Hash[array.map{|item| [item[:id], item]}]
end

如果我们能说服 Matz,你至少可以:

def build_hash(array)
  array.map{|item| [item[:id], item]}.to_h
end

还有其他关于创建哈希的新方法的请求。

于 2013-03-01T19:54:21.523 回答
1

那么在这种情况下,您可以使用inject并执行以下操作:

def build_hash(array)
  array.inject({}) { |init, item| init[item[:id]] = item; init }
end
于 2013-03-01T19:22:08.237 回答
1
{}.tap { |h| array.each { |a| h[a[:id]] = a } }
于 2013-03-01T19:22:49.593 回答
1

这里也是一种如何转换ArrayHash.

list_items = ["1", "Foo", "2", "Bar", "3" , "Baz"]

 hss = Hash[*list_items]
  • 参数必须是偶数,否则会引发致命错误,因为奇数个参数无法映射到一系列键/值对。

{"1"=>​​"Foo", "2"=>"Bar", "3"=>"Baz"}

于 2013-03-01T19:43:40.430 回答