21

我正在寻找一种更惯用的方法来过滤掉数组的 nil-or-empty 元素。

我有很多形式的方法:

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

这将获取 and 的结果some_methodsome_other_method仅返回非 nil (compact本质上等同于reject(&:nil?))和非空的结果。

Array 或 Enumerable 中是否有任何东西可以一次性获得相同的结果?

4

6 回答 6

21

reject(&:blank?)在 Rails 中,您可以执行select(&:present?).

如果这不适用于 Rails 应用程序,并且您经常这样做,我建议您定义自己的帮助程序String或您要过滤的任何其他内容。

class String
  alias :blank? :empty?
end

class NilClass
  def blank?
    true
  end
end
于 2012-11-21T19:04:12.163 回答
3

以下代码应该可以解决问题:

[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
于 2012-11-21T19:06:15.860 回答
2

猴子补丁接受了吗?:)

你可以试试这个:

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?

于 2012-11-21T19:31:44.370 回答
2

也许我们只需要一个简单的 NilClass 扩展?

class NilClass
  def empty?
    true
  end
end
于 2012-11-25T10:51:05.507 回答
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] 

你的呢?我们还需要更多东西吗?请通过投票来表达您的疑虑或表示默许,以帮助推动上游的语言更改。

开心!

于 2013-05-15T11:58:33.557 回答
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

有关编写 Ruby 代码的更多惯用方式,您应该阅读这篇文章

于 2017-04-22T23:08:24.460 回答