将数组拆分为散列
Splitting up an array into a hash
我有一个大约有860项的数组,我想把它变成一个散列,数组结构是(Key1, value 1, value2, value 3, Key2, value 1, value 2, value 3。 ..........等等)除了在现实生活中它看起来像(彼得,150、39、345,约翰,123、450、402,玛丽,145、345、506...... ……)。原来这些是我调换在一起的四个数组,所以我可以从 4 个独立的数组开始达到相同的最终目标。
我要
Hash {Peter=> [150, 39, 345], John=>[123,450,402], Mary => [145,345,506] etc etc
我觉得应该有一个很好的巧妙方法来做到这一点,但它让我望而却步,可能是因为我了解得不够 ruby。
如果您知道数据总是以 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]}
我认为这是最干净的方法。
另一种方式:
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]}
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 made its debut in Ruby v2.3. One could alternatively use 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]
Original these are four arrays which I have transposed together, so I could reach the same end goal by starting from 4 independent arrays.
我假设你有这样的事情开始:
a = ["Peter", "John", "Mary"]
b = [150, 123, 145]
c = [39, 450, 345]
d = [345, 402, 506]
您可以通过 zip
:
组合 "value" 个数组
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
returns结果一样
试试这个
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]}
我有一个大约有860项的数组,我想把它变成一个散列,数组结构是(Key1, value 1, value2, value 3, Key2, value 1, value 2, value 3。 ..........等等)除了在现实生活中它看起来像(彼得,150、39、345,约翰,123、450、402,玛丽,145、345、506...... ……)。原来这些是我调换在一起的四个数组,所以我可以从 4 个独立的数组开始达到相同的最终目标。
我要
Hash {Peter=> [150, 39, 345], John=>[123,450,402], Mary => [145,345,506] etc etc
我觉得应该有一个很好的巧妙方法来做到这一点,但它让我望而却步,可能是因为我了解得不够 ruby。
如果您知道数据总是以 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]}
我认为这是最干净的方法。
另一种方式:
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]}
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 made its debut in Ruby v2.3. One could alternatively use 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]
Original these are four arrays which I have transposed together, so I could reach the same end goal by starting from 4 independent arrays.
我假设你有这样的事情开始:
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
:
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
returns结果一样
试试这个
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]}