簡體   English   中英

給定嵌套長度不同的嵌套數組在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),第二個元素(在這種情況下為蘋果或香蕉)不會有所不同。 因此,只要任何兩個嵌套數組之間的第一個元素相同,我就希望將它們合並在一起。

同樣,數據可確保共享相同第一個元素的數組的編號之間不會發生沖突。 但是,這些數字應在合並后保持其索引位置。 這很關鍵。

我不太確定該如何處理。 我正在考慮創建一個空數組,然后遍歷嵌套數組以檢查第一個元素是否包含在新數組中。 如果不是,則將該陣列推入新陣列。 如果是這樣,請合並它們。 我的代碼不起作用(我得到一個空數組)...

    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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM