2017-08-24 48 views
11

我有一個數組是這樣的:刪除尾隨從陣列零值紅寶石

[["a", nil, nil, nil], ["b", nil, "c", nil], [nil, nil, nil, nil]] 

我想從陣列中刪除所有的紅寶石尾隨零值。

我試過arr.map {|x| x.pop until x.last}但這種方法的問題是,當數組的所有值都是nil時,就像給定數組中的第三個數組一樣,循環會發生。

由於until x.last條件,如果所有的值都是零,那麼映射函數應該返回一個空數組?

這應該是什麼條件。

輸出應該

[['a'],['b','nil','c'],[]] 

記得我只是想刪除不落後之間的值nil

+3

應該在兩者之間'nil'值真的被轉換成''nil''字符串? – Stefan

回答

10

您是在正確的道路,只是修改你的代碼位:

array.each { |e| e.pop until !e.last.nil? || e.empty? } 
#=> [["a"], ["b", nil, "c"], []] 

這比使用reverse更快 - reversedrop_while

+0

我想關鍵的一點是如果想要改變原件的話。 Allthough複製+彈出可能仍然更快,真實。 –

12

爲此,您可以忘記外層數組,然後使用map將解決方案應用於所有內層數組。

drop_while將返回一個沒有滿足某些條件的所有前導項目的新陣列(例如nil?)。你想跟蹤結合reverse

[nil,nil,5,nil,6,nil].reverse.drop_while(&:nil?).reverse 
[nil, nil, 5, nil, 6] 

然後對所有數組使用map。

arr = [["a", nil, nil, nil], ["b", nil, "c", nil], [nil, nil, nil, nil]] 
arr.map{|a| a.reverse.drop_while(&:nil?).reverse} 
[["a"], ["b", nil, "c"], []] 

如果你想要的任何剩餘nil實際上是一個字符串,您可以與執行任何你喜歡的這種轉換的另一地圖它結合起來。

4

還有一個選擇是使用rindex

arr.map do |e| 
    index = e.rindex { |i| !i.nil? } # the last index of not `nil` element 
    index ? e.first(index + 1) : e 
end 
#=> [["a"], ["b", nil, "c"], []]