数组到Hash Ruby

Array to Hash Ruby

好吧,这是交易,我在谷歌上搜索了很久,想找到解决办法,虽然有很多人,但他们似乎没有做我要找的工作。

基本上我有一个这样的数组

1
["item 1","item 2","item 3","item 4"]

我想把这个转换成散列,所以看起来像这样

1
{"item 1" =>"item 2","item 3" =>"item 4" }

即"偶数"索引上的项是键,"奇数"索引上的项是值。

有什么办法可以干净利落地做到这一点吗?我认为一个蛮力的方法是将所有偶数索引提取到一个单独的数组中,然后循环它们以添加值。


1
2
a = ["item 1","item 2","item 3","item 4"]
h = Hash[*a] # => {"item 1" =>"item 2","item 3" =>"item 4" }

就是这样。*被称为splat运算符。

每个@mike lewis都要注意一点(在评论中):"要非常小心。Ruby在堆栈上展开展开。如果您对一个大数据集执行此操作,那么应该将您的堆栈吹出。"

所以,对于大多数一般的用例来说,这个方法是很好的,但是如果您想对大量数据进行转换,可以使用不同的方法。例如,@?Ukasz Niemier(也在注释中)为大型数据集提供了这种方法:

1
h = Hash[a.each_slice(2).to_a]


Ruby2.1.0在数组上引入了一个to_h方法,如果原始数组由键值对数组组成,那么它可以满足您的需要:http://www.ruby-doc.org/core-2.1.0/array.html method-i-to-u h。

1
2
[[:foo, :bar], [1, 2]].to_h
# => {:foo => :bar, 1 => 2}


只需对数组中的值使用Hash.[]。例如:

1
2
arr = [1,2,3,4]
Hash[*arr] #=> gives {1 => 2, 3 => 4}


或者,如果您有一个[key, value]数组数组,则可以执行以下操作:

1
2
3
[[1, 2], [3, 4]].inject({}) do |r, s|
  r.merge!({s[0] => s[1]})
end # => { 1 => 2, 3 => 4 }


这是我在谷歌搜索时要找的:

[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v }
=> {:a=>1, :b=>2}


Enumerator包括Enumerable。由于2.1Enumerable也有一个方法#to_h。所以,我们可以写:

1
2
3
a = ["item 1","item 2","item 3","item 4"]
a.each_slice(2).to_h
# => {"item 1"=>"item 2","item 3"=>"item 4"}

因为没有block的#each_slice给了我们Enumerator,根据上面的解释,我们可以在Enumerator对象上调用#to_h方法。


您可以这样尝试,对于单个数组

1
2
3
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"}

用于数组

1
2
3
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}

1
2
a = ["item 1","item 2","item 3","item 4"]
Hash[ a.each_slice( 2 ).map { |e| e } ]

或者,如果你讨厌Hash[ ... ]

1
a.each_slice( 2 ).each_with_object Hash.new do |(k, v), h| h[k] = v end

或者,如果你是一个懒散的功能编程爱好者:

1
2
3
4
5
6
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"