[英]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),第二個元素(在這種情況下為蘋果或香蕉)不會有所不同。 因此,只要任何兩個嵌套數組之間的第一個元素相同,我就希望將它們合並在一起。
同樣,數據可確保共享相同第一個元素的數組的編號之間不會發生沖突。 但是,這些數字應在合並后保持其索引位置。 這很關鍵。
我不太確定該如何處理。 我正在考慮創建一個空數組,然后遍歷嵌套數組以檢查第一個元素是否包含在新數組中。 如果不是,則將該陣列推入新陣列。 如果是這樣,請合並它們。 我的代碼不起作用(我得到一個空數組)...
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]
有幾種方法可以做到這一點。 一種是使用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
的塊並分配給block變量:
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.reduce { |d,e| d | e }
a.reduce { |d,e| d | e }
,它僅僅是a的三個元素(數組)的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]
類似的計算是為第二元件執行a
傳遞給map
的塊。
您可以使用哈希並將其轉換為數組
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]]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.