假设它们在 Ruby 中共享一个元素,如何合并不同长度的嵌套数组?
How to merge nested arrays of varying lengths, given they share an element in Ruby?
我有由字符串和整数组成的嵌套数组,我想根据每个数组的第一个元素合并它们。假设这些是项目 ID。嵌套数组的长度不同,但只要每个嵌套数组的第一个元素相同,我想将它们合并在一起。
我的数据可能是这样的:
arr = [['00', 'apples', nil, nil, 8],
['00', 'apples', nil, 2],
['00', 'apples', nil, nil, nil, 3],
['01', 'bananas', 2],
['01', 'bananas', nil, nil, 3],
['01', 'bananas', nil, 5]]
所以我想压缩这些数组,使它们看起来像:
arr = [['00', 'apples', nil, 2, 8, 3],
['01', 'bananas', 2, 5, 3]]
对于给定的第一个元素(00 或 01),不会出现第二个元素(在本例中为苹果或香蕉)不同的情况。因此,只要第一个元素在任何两个嵌套数组之间是相同的,我就想将它们合并在一起。
此外,数据保证共享相同第一个元素的数组的数字之间不会发生冲突。但是,数字应保持其索引位置 post-merge。这很关键。
我不太确定如何处理这个问题。我正在考虑创建一个空数组,然后遍历嵌套数组以检查第一个元素是否包含在新数组中。如果不是,将该数组推送到新数组。如果是这样,请合并它们。我的代码不起作用(我得到一个空数组)...
new_array = Array.new
old_array.each do |o|
new_array.each do |n|
if o[0] == n[0]
n = o | n
else
n.push(o)
end
end
end
我调查了 .reduce(:|)
但它给了我不想要的结果:
arr = [["00", "apples", nil, nil, nil, 8],
["00", "apples", nil, nil, nil, nil, 1],
["00", "apples", nil, nil, 1]]
arr.reduce(:|)
=> ["00", "apples", nil, 8, 1]
我期待:=> ["00", "apples", nil, nil, 1, 8, 1]
您可以使用散列并将其转换为数组
new_hash = {}
old_array.each do |o|
new_hash[o[0]] ||= []
o.each_with_index do |n, i|
new_hash[o[0]][i] ||= n
end
end
puts new_hash.inspect
puts new_hash.map { |k,v| v }.inspect
这将导致
{"00"=>["00", "apples", nil, 2, 8, 3], "01"=>["01", "bananas", 2, 5, 3]}
[["00", "apples", nil, 2, 8, 3], ["01", "bananas", 2, 5, 3]]
有几种方法可以做到这一点。一种是使用Enumerable#group_by。其他人可能会提到合并哈希的方法。
arr = [
['00', 'apples', nil, nil, 8],
['00', 'apples', nil, 2],
['00', 'apples', nil, nil, nil, 3],
['01', 'bananas', 2],
['01', 'bananas', nil, nil, 3],
['01', 'bananas', nil, 5]
]
arr.group_by(&:first).values.map { |a| a.reduce(:|) }
#=> [["00", "apples", nil, 8, 2, 3], ["01", "bananas", 2, nil, 3, 5]]
步骤如下:
b = arr.group_by(&:first)
#=> {"00"=>[["00", "apples", nil, nil, 8], ["00", "apples", nil, 2],
# ["00", "apples", nil, nil, nil, 3]],
# "01"=>[["01", "bananas", 2], ["01", "bananas", nil, nil, 3],
# ["01", "bananas", nil, 5]]}
c = b.values
#=> [[["00", "apples", nil, nil, 8], ["00", "apples", nil, 2],
# ["00", "apples", nil, nil, nil, 3]],
# [["01", "bananas", 2], ["01", "bananas", nil, nil, 3],
# ["01", "bananas", nil, 5]]]
c.map { |a| a.reduce(:|) }
#=> [["00", "apples", nil, 8, 2, 3], ["01", "bananas", 2, nil, 3, 5]]
c
的第一个元素传递给map
的块并赋值给块变量:
a = [["00", "apples", nil, nil, 8], ["00", "apples", nil, 2],
["00", "apples", nil, nil, nil, 3]]
a.reduce(:|)
给出与 a.reduce { |d,e| d | e }
相同的结果,它只是 a
:
的三个元素(数组)的并集
(["00", "apples", nil, nil, 8] | ["00", "apples", nil, 2]) |
["00", "apples", nil, nil, nil, 3]]
#=> ["00", "apples", nil, 8, 2] | ["00", "apples", nil, nil, nil, 3]
#=> ["00", "apples", nil, 8, 2, 3]
对传递给 map
块的 a
的第二个元素执行类似的计算。
我有由字符串和整数组成的嵌套数组,我想根据每个数组的第一个元素合并它们。假设这些是项目 ID。嵌套数组的长度不同,但只要每个嵌套数组的第一个元素相同,我想将它们合并在一起。
我的数据可能是这样的:
arr = [['00', 'apples', nil, nil, 8],
['00', 'apples', nil, 2],
['00', 'apples', nil, nil, nil, 3],
['01', 'bananas', 2],
['01', 'bananas', nil, nil, 3],
['01', 'bananas', nil, 5]]
所以我想压缩这些数组,使它们看起来像:
arr = [['00', 'apples', nil, 2, 8, 3],
['01', 'bananas', 2, 5, 3]]
对于给定的第一个元素(00 或 01),不会出现第二个元素(在本例中为苹果或香蕉)不同的情况。因此,只要第一个元素在任何两个嵌套数组之间是相同的,我就想将它们合并在一起。
此外,数据保证共享相同第一个元素的数组的数字之间不会发生冲突。但是,数字应保持其索引位置 post-merge。这很关键。
我不太确定如何处理这个问题。我正在考虑创建一个空数组,然后遍历嵌套数组以检查第一个元素是否包含在新数组中。如果不是,将该数组推送到新数组。如果是这样,请合并它们。我的代码不起作用(我得到一个空数组)...
new_array = Array.new
old_array.each do |o|
new_array.each do |n|
if o[0] == n[0]
n = o | n
else
n.push(o)
end
end
end
我调查了 .reduce(:|)
但它给了我不想要的结果:
arr = [["00", "apples", nil, nil, nil, 8],
["00", "apples", nil, nil, nil, nil, 1],
["00", "apples", nil, nil, 1]]
arr.reduce(:|)
=> ["00", "apples", nil, 8, 1]
我期待:=> ["00", "apples", nil, nil, 1, 8, 1]
您可以使用散列并将其转换为数组
new_hash = {}
old_array.each do |o|
new_hash[o[0]] ||= []
o.each_with_index do |n, i|
new_hash[o[0]][i] ||= n
end
end
puts new_hash.inspect
puts new_hash.map { |k,v| v }.inspect
这将导致
{"00"=>["00", "apples", nil, 2, 8, 3], "01"=>["01", "bananas", 2, 5, 3]}
[["00", "apples", nil, 2, 8, 3], ["01", "bananas", 2, 5, 3]]
有几种方法可以做到这一点。一种是使用Enumerable#group_by。其他人可能会提到合并哈希的方法。
arr = [
['00', 'apples', nil, nil, 8],
['00', 'apples', nil, 2],
['00', 'apples', nil, nil, nil, 3],
['01', 'bananas', 2],
['01', 'bananas', nil, nil, 3],
['01', 'bananas', nil, 5]
]
arr.group_by(&:first).values.map { |a| a.reduce(:|) }
#=> [["00", "apples", nil, 8, 2, 3], ["01", "bananas", 2, nil, 3, 5]]
步骤如下:
b = arr.group_by(&:first)
#=> {"00"=>[["00", "apples", nil, nil, 8], ["00", "apples", nil, 2],
# ["00", "apples", nil, nil, nil, 3]],
# "01"=>[["01", "bananas", 2], ["01", "bananas", nil, nil, 3],
# ["01", "bananas", nil, 5]]}
c = b.values
#=> [[["00", "apples", nil, nil, 8], ["00", "apples", nil, 2],
# ["00", "apples", nil, nil, nil, 3]],
# [["01", "bananas", 2], ["01", "bananas", nil, nil, 3],
# ["01", "bananas", nil, 5]]]
c.map { |a| a.reduce(:|) }
#=> [["00", "apples", nil, 8, 2, 3], ["01", "bananas", 2, nil, 3, 5]]
c
的第一个元素传递给map
的块并赋值给块变量:
a = [["00", "apples", nil, nil, 8], ["00", "apples", nil, 2],
["00", "apples", nil, nil, nil, 3]]
a.reduce(:|)
给出与 a.reduce { |d,e| d | e }
相同的结果,它只是 a
:
(["00", "apples", nil, nil, 8] | ["00", "apples", nil, 2]) |
["00", "apples", nil, nil, nil, 3]]
#=> ["00", "apples", nil, 8, 2] | ["00", "apples", nil, nil, nil, 3]
#=> ["00", "apples", nil, 8, 2, 3]
对传递给 map
块的 a
的第二个元素执行类似的计算。