数组哈希ruby
好吧,所以这里的交易,我一直在search谷歌寻找解决办法,虽然有很多外面,他们似乎没有做我正在寻找的工作。
基本上我有一个这样的数组结构
["item 1", "item 2", "item 3", "item 4"]
我想把它转换成一个哈希,所以它看起来像这样
{ "item 1" => "item 2", "item 3" => "item 4" }
即“偶数”索引上的项是键,“奇数”索引上的项是数值。
任何想法如何做到这一点干净? 我想蛮力的方法是把所有的偶数索引都放到一个单独的数组中,然后在它们周围循环来添加值。
使用to_h
:
a = ["item 1", "item 2", "item 3", "item 4"] h = a.to_h # => { "item 1" => "item 2", "item 3" => "item 4" }
对于后人,下面是ruby <2.1.0版本的答案:
a = ["item 1", "item 2", "item 3", "item 4"] h = Hash[*a] # => { "item 1" => "item 2", "item 3" => "item 4" }
而已。 *
被称为splat操作符。
每个@Mike Lewis的注意事项(在评论中):“要小心这个,Ruby会把splats扩展到堆栈上,如果你用大数据集来做这件事,那么期望把堆栈炸掉。
所以,对于大多数通用的用例来说,这个方法是好的,但是如果你想对大量的数据进行转换,可以使用一种不同的方法。 例如,@ŁukaszNiemier(也在评论中)为大数据集提供了这种方法:
h = Hash[a.each_slice(2).to_a]
Ruby 2.1.0在Array上引入了一个to_h
方法,如果原始数组由键值对组成,就可以执行所需的操作: http : to_h
方法-i-to_h 。
[[:foo, :bar], [1, 2]].to_h # => {:foo => :bar, 1 => 2}
或者如果你有一个[key, value]
数组的数组,你可以这样做:
[[1, 2], [3, 4]].inject({}) do |r, s| r.merge!({s[0] => s[1]}) end # => { 1 => 2, 3 => 4 }
只需使用Hash.[]
与数组中的值。 例如:
arr = [1,2,3,4] Hash[*arr] #=> gives {1 => 2, 3 => 4}
Enumerator
包含Enumerable
。 从2.1
, Enumerable
也有一个方法#to_h
。 这就是为什么我们可以这样写:
a = ["item 1", "item 2", "item 3", "item 4"] a.each_slice(2).to_h # => {"item 1"=>"item 2", "item 3"=>"item 4"}
因为#each_slice
without block给了我们Enumerator
,并且按照上面的解释,我们可以在Enumerator
对象上调用#to_h
方法。
a = ["item 1", "item 2", "item 3", "item 4"] Hash[ a.each_slice( 2 ).map { |e| e } ]
或者,如果你讨厌Hash[ ... ]
:
a.each_slice( 2 ).each_with_object Hash.new do |(k, v), h| h[k] = v end
或者,如果你是一个破坏函数式编程的懒惰迷:
h = a.lazy.each_slice( 2 ).tap { |a| break Hash.new { |h, k| h[k] = a.find { |e, _| e == k }[1] } } #=> {} h["item 1"] #=> "item 2" h["item 3"] #=> "item 4"
你可以像这样尝试单个数组
irb(main):019:0> a = ["item 1", "item 2", "item 3", "item 4"] => ["item 1", "item 2", "item 3", "item 4"] irb(main):020:0> Hash[*a] => {"item 1"=>"item 2", "item 3"=>"item 4"}
数组的数组
irb(main):022:0> a = [[1, 2], [3, 4]] => [[1, 2], [3, 4]] irb(main):023:0> Hash[*a.flatten] => {1=>2, 3=>4}
这是我一直在寻找的时候这个search:
[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v } => {:a=>1, :b=>2}