从Array中删除前导nils

时间:2015-08-16 20:22:15

标签: ruby

我有一个像这样的数组:

[nil, nil, nil, 2, 4, 6, 1, nil, nil, 3, 4, 6]

我需要的是一个很好的方法来删除所有前导 nils(因此compact!很糟糕),并删除了nils的数量(所以drop_while很糟糕)。

2 个答案:

答案 0 :(得分:6)

以下是三种方法。请注意,以下内容经过了多次修改。

arr0 = [nil, nil, nil, 2, 4, 6, 1, nil, nil, 3, 4, 6]
arr1 = [nil, nil]
arr2 = [1, 2]

<强>#1

def remove_leading_nils(arr)
  i = arr.index { |e| !e.nil? } || arr.size
  arr.slice!(0...i)
  i
end

remove_leading_nils(arr0) #=> 3
arr0                      #=> [2, 4, 6, 1, nil, nil, 3, 4, 6] 

remove_leading_nils(arr1) #=> 2
arr1                      #=> [] 

remove_leading_nils(arr2) #=> 0
arr2                      #=> [1,2] 

<强>#2

def remove_leading_nils(arr)
  arr.size.times.with_object([]) { |_,a| a << arr.shift unless arr.first }.size
end

<强>#3

我更喜欢这个,因为它更简单,我觉得它最好:

def remove_leading_nils(arr)
  sz = arr.size
  arr.shift while !arr.empty? && arr.first.nil?
  sz - arr.size
end

与方法#1一样,方法#2和#3与arr0arr1arr2具有相同的返回值。

答案 1 :(得分:2)

可能不是一个好主意,但如果你坚持单行:

arr.instance_eval { shift(index { |element| !element.nil? } || size) }.count

<小时/> 编辑:对于任何人未来的参考,我们同意的更好看的版本:

arr.shift(arr.index(&:itself) || arr.size).count