结合'uniq'和'compact'的数组方法

时间:2015-04-07 08:15:13

标签: ruby

我正在尝试在数组中查找唯一元素并从中删除nil值。我的解决方案如下:

@array = [1, 2, 1, 1, 2, 3, 4, nil, 5, nil, 5] 
@array.uniq.compact # => [1, 2, 3, 4, 5] 

是否有任何一种方法可以同时执行这两项操作?如果没有,哪个有效,@array.uniq.compact@array.compact.uniq

2 个答案:

答案 0 :(得分:7)

不,但您可以按照自己喜欢的顺序附加它们,即

array.uniq.compact
array.compact.uniq

正如phts所指出的,你可以将一个块传递给uniq,但我认为这不是uniq.compact的替代方案。

为了获得更好的速度,以下内容可能有所帮助:

[].tap do |new_array|
  hash = {}
  original_array.each do |element|
    next if element.nil? || !hash[element].nil?
    new_array << (hash[element] = element)
  end
end

最后,如果速度不是问题,并且您经常使用此方法,那么您可以创建自己的方法:

class Array
  def compact_uniq
    self.compact.uniq
  end

  def compact_blank # in case you want to remove all 'blanks' as well
    self.compact.reject(&:blank?)
  end
end

答案 1 :(得分:2)

没有这样的方法。

我认为@array.compact.uniq@array.uniq.compact是相同的,因为这两种方法都有O(N)的复杂性。

正如@Stefan提到的那样使用!的方法可能会破坏内存使用。


作为替代方法,您可以仅使用uniq方法和一个块,该块返回除nil之外的肯定存在的元素,因此将跳过它。例如

@array.uniq { |s| s.nil? ? @array.first : s }

但在这种情况下,您必须确保数组的第一个元素不是nil