我正在寻找一种更惯用的方法来过滤掉数组中的零或空元素。
我有很多以下形式的方法:
def joined
[some_method, some_other_method].compact.reject(&:empty?).join(' - ')
end
这将获取
some_method
和 some_other_method
的结果,并仅返回非零(compact
本质上相当于 reject(&:nil?)
)且非空的结果。
数组或枚举中是否有任何东西可以一次性获得相同的结果?
在 Rails 中,您可以执行
reject(&:blank?)
,或者等效地,select(&:present?)
。
如果这不是针对 Rails 应用程序,并且您经常这样做,我建议您在
String
或您正在过滤的任何其他内容上定义自己的帮助器。
class String
alias :blank? :empty?
end
class NilClass
def blank?
true
end
end
以下代码应该可以解决问题:
[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
接受猴子补丁吗? :)
你可以试试这个:
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?
的对象
也许我们只需要对 NilClass 进行一个简单的扩展?
class NilClass
def empty?
true
end
end
@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]
你的呢?我们还需要更多东西吗?请表达您的疑虑或通过投票来表示默许,以帮助推动上游的语言变革。
n欢乐!
我认为你不需要使用
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
有关更多编写 Ruby 代码的惯用方法,您应该阅读这篇文章
ActiveSupport
,Rails 的一部分,有这个方法,blank_empty_nil_filters
gem 也有这个方法:is_blank?
和 is_empty?
。
两者之间是有区别的。有些用例可以容忍空白(空白),有些则不能。
ActiveSupport
是一个更大、更全面的 gem,使用 Regexp.match
来确定空白,而 blank_empty_nil_filters
gem 代码使用非破坏性条带,这既更快又对非 UTF8 字符串错误条件不太敏感。