我有一个大约860项的数组,我想把它变成一个哈希,数组结构是(Key1,value 1,value2,value 3,Key2,value 1,value 2,value 3 ... ........等等除了在现实生活中它看起来像(Peter,150,39,345,John,123,450,402,Mary,145,345,506 ........ ....)。原来这些是我已经转换到的四个阵列,所以我可以通过从4个独立阵列开始达到相同的最终目标。
我想
Hash {Peter=> [150, 39, 345], John=>[123,450,402], Mary => [145,345,506] etc etc
我觉得应该有一个很好的方法来做到这一点,但它让我望而却步,可能是因为我不知道足够的红宝石。
答案 0 :(得分:4)
还有一种方法:
l = ['Peter', 150, 39, 345, 'John', 123, 450, 402, 'Mary', 145, 345, 506]
Hash[*l.each_slice(4).flat_map { |a, *b| [a, b] }]
#=> {"Peter"=>[150, 39, 345],
# "John" =>[123, 450, 402],
# "Mary" =>[145, 345, 506]}
如果您已有阵列,解决方案将更加简单:
arrays = [array_1, array_2, array_3]
Hash[*arrays.flat_map {|a, *b| [a, b]} ]
#=> {"Peter"=>[150, 39, 345], "John"=>[123, 450, 402], "Mary"=>[145, 345, 506]}
答案 1 :(得分:3)
arr = ['Peter', 150, 39, 345, 'John', 123, 450, 'Mary', 145, 345, 506, 222]
arr.slice_before {|a| String === a }.
each_with_object({}) {|(f,*rest), h| h[f] = rest}
#=> {"Peter"=>[150, 39, 345], "John"=>[123, 450], "Mary"=>[145, 345, 506, 222]}
Enumerable#slice_before在Ruby v2.3中首次亮相。也可以使用Enumerable#slice_when,这是v2.2中的新内容。
以下是使用早期版本Ruby的几种方法。
arr.chunk { |e| String === e }.
each_slice(2).
with_object({}) { |((_,(k)),(_,v)), h| h[k] = v }
和
a = []
enum = arr.to_enum
loop do
o = enum.next
(String === o) ? a << [o,[]] : a.last.last << o
end
Hash[a]
答案 2 :(得分:1)
如果您知道数据总是以4组为准:
l = ['Peter', 150, 39, 345, 'John', 123, 450, 402, 'Mary', 145, 345, 506]
h = {}
l.each_slice(4).each do |chunk|
h[chunk[0]] = chunk[1..chunk.length]
end
或者,如果你知道键总是字符串:
l = ['Peter', 150, 39, 345, 'John', 123, 450, 402, 'Mary', 145, 345, 506]
h = {}
current_key = ""
l.each do |item|
if item.is_a? String
current_key = item
h[item] = []
else
h[current_key] << item
end
end
基本上,你需要弄清楚如何恰当地切割数组然后循环。
此外,如果您已将它们作为单独的阵列获得,您可以轻松地:
array_1 = ['Peter', 150, 39, 345]
array_2 = ['John', 123, 450, 402]
array_3 = ['Mary', 145, 345, 506]
h = {}
[array_1,array_2, array_3].each do |a|
h[a[0]] = a[1:a.length]
end
# One line version:
[array_1,array_2, array_3].map{|a| h[a[0]] = a[1..a.length]}
我认为这是最干净的方法。
答案 3 :(得分:1)
原来这些是我已经转换过的四个阵列,因此我可以从4个独立阵列开始达到相同的最终目标。
我假设你有这样的事情开头:
a = ["Peter", "John", "Mary"]
b = [150, 123, 145]
c = [39, 450, 345]
d = [345, 402, 506]
您可以通过zip
组合“值”数组:
values = b.zip(c, d)
#=> [[150, 39, 345], [123, 450, 402], [145, 345, 506]]
通过另一个zip
添加“key”数组:
a.zip(values)
#=> [["Peter", [150, 39, 345]], ["John", [123, 450, 402]], ["Mary", [145, 345, 506]]]
这已经是正确的结构,所以我们可以调用to_h
:
a.zip(values).to_h
#=> {"Peter"=>[150, 39, 345], "John"=>[123, 450, 402], "Mary"=>[145, 345, 506]}
当然你不需要中间变量,a.zip(b.zip(c, d)).to_h
会返回相同的结果。
答案 4 :(得分:0)
试试这个
l = ['Peter', 150, 39, 345, 'John', 123, 450, 402, 'Mary', 145, 345, 506]
l.each_slice(4).to_a.inject({}){|acc, temp| acc[temp.first]=temp.last(3); acc}
#=>{"Peter"=>[150, 39, 345], "John"=>[123, 450, 402], "Mary"=>[145, 345, 506]}