用于零或空的惯用Ruby过滤器?

时间:2012-11-21 18:52:21

标签: ruby idioms enumerable

我正在寻找一种更惯用的方法来过滤掉数组中的空元素。

我有很多形式的方法:

def joined
    [some_method, some_other_method].compact.reject(&:empty?).join(' - ')
end

这将取some_methodsome_other_method的结果,并仅返回非零(compact基本上等同于reject(&:nil?))的一个({1}}而且非空。

Array或Enumerable中有什么东西可以一次性获得相同的东西吗?

6 个答案:

答案 0 :(得分:17)

在Rails中,您可以reject(&:blank?)或相当于select(&:present?)

如果这不适用于Rails应用程序,并且你做了很多,我建议你在String或你正在过滤的其他任何内容上定义你自己的帮助。

class String
  alias :blank? :empty?
end

class NilClass
  def blank?
    true
  end
end

答案 1 :(得分:2)

以下代码可以解决这个问题:

[some_method, some_other_method].reject{|i| i.nil? || i.empty? }

它可以很容易地用于扩展数组类:

class Array

  def purge
    self.reject{|i| i.nil? || i.empty? }
  end 

end

然后你可以这样做:

[some_method, some_other_method].purge

答案 2 :(得分:2)

接受monkeypatches? :)

你可以试试这个:

class Array
  def tight
    self.compact.reject { |i| i.size.zero? }
  end
end

p [nil, 1, ''].tight
#=> [1]
p ['', nil, 2].tight
#=> [2]

它可以处理响应size的任何对象,而不仅仅是响应empty?的对象

答案 3 :(得分:2)

也许我们需要对NilClass进行一次简单的扩展?

class NilClass
  def empty?
    true
  end
end

答案 4 :(得分:0)

@trans享受我的+1,但经过进一步审议后,我得出了以下结论。

如果我们的前提是所有内容都是Object,那么我们实际需要的只是class Object的补丁

class Object
    def empty?
        self == 0 or not self
    end
end

满足我的要求:

1.9.3 :001 > d=[Object.new, Class, {a:nil}, 'a', '', [], 1, 1.1, 0, 0.0, 0x0, 0E0, true, false, nil]
 => [#<Object:0x007fd56c086918>, Class, {:a=>nil}, "a", "", [], 1, 1.1, 0, 0.0, 0, 0.0, true, false, nil] 
1.9.3 :002 > d.reject(&:empty?)
 => [#<Object:0x007fd56c086918>, Class, {:a=>nil}, "a", 1, 1.1, true] 

你呢?我们还需要更多东西吗?请通过投票表明您的疑虑或表达沉默的协议,以帮助推动上游的语言变革。

的nJoy!

答案 5 :(得分:0)

我认为您不需要使用reject方法。只需使用Array的select方法。

def joined
  [some_method, some_other_method].select { |method| method.present? }
end

甚至更好:

def joined
  [some_method, some_other_method].select(&:present?)
end

要获得更多 Idiomatic way to write Ruby code ,您应该阅读此article