检查数组不为空:是吗?


189

这样做不好,检查数组是否使用空any?的方法?

a = [1,2,3]

a.any?
=> true

a.clear

a.any?
=> false

还是更好用unless a.empty?

Answers:


246

any?not empty?某些情况不同。

>> [nil, 1].any?
=> true
>> [nil, nil].any?
=> false

从文档中:

如果没有给出该块,Ruby将添加一个隐式块{| obj | obj}(如果不是集合成员中的至少一个不是false或nil,则返回true)。


8
有相反的功能empty?吗?
RocketR 2012年

12
@RocketR您可能想签出present?方法。
dantheta

15
@dantastic #present?仅适用于Rails。在纯Ruby中,您会得到NoMethodError: undefined method 'present?' for Array
RocketR 2012年

6
不完全只限于Rails,Active Support可以不带Rails使用,只需要require 'activesupport'
塞尔吉奥A.15年

83

数组将其值评估为null true或为空的区别。

该方法empty?来自Array类
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F

它用于检查数组是否包含某些内容。这包括计算结果为的事物false,例如nilfalse

>> a = []
=> []
>> a.empty?
=> true
>> a = [nil, false]
=> [nil, false]
>> a.empty?
=> false
>> a = [nil]
=> [nil]
>> a.empty?
=> false

该方法any?来自Enumerable模块。
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F

它用于评估数组中的“ any”值是否等于true。与none?all?和相似的方法one?,它们都只是检查以查看可以评估多少次正确。这与在数组中找到的值的计数无关。

情况1

>> a = []
=> []
>> a.any?
=> false
>> a.one?
=> false
>> a.all?
=> true
>> a.none?
=> true

情况2

>> a = [nil, true]
=> [nil, true]
>> a.any?
=> true
>> a.one?
=> true
>> a.all?
=> false
>> a.none?
=> false

情况3

>> a = [true, true]
=> [true, true]
>> a.any?
=> true
>> a.one?
=> false
>> a.all?
=> true
>> a.none?
=> false

31

给该语句加上一个感叹号,可以让您知道该数组是否为空。因此,就您而言-

a = [1,2,3]
!a.empty?
=> true

27
双重否定?你是认真的吗?
3lvis 2014年

29
他是如此不认真!
亚历山大·伯德

5
呵呵。双重否定并不理想,在这种特定情况下似乎更具可读性。
Denny Abraham Cheriyan

11
双重否定是原始问题“检查数组是否为空”的一部分。这回答了问题。
mattfitzgerald '16

30

避免any?使用大型阵列。

  • any?O(n)
  • empty?O(1)

any? 不会检查长度,但实际上会扫描整个数组以查找真实元素。

static VALUE
rb_ary_any_p(VALUE ary)
{
  long i, len = RARRAY_LEN(ary);
  const VALUE *ptr = RARRAY_CONST_PTR(ary);

  if (!len) return Qfalse;
  if (!rb_block_given_p()) {
    for (i = 0; i < len; ++i) if (RTEST(ptr[i])) return Qtrue;
  }
  else {
    for (i = 0; i < RARRAY_LEN(ary); ++i) {
        if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
    }
  }
  return Qfalse;
}

empty? 另一方面只检查数组的长度。

static VALUE
rb_ary_empty_p(VALUE ary)
{
  if (RARRAY_LEN(ary) == 0)
    return Qtrue;
  return Qfalse;
}

如果您有以许多nil值开头的“稀疏”数组(例如刚创建的数组),则差异是相关的。


在此用例中,仅当您具有以大量nil值开头的“稀疏”数组any?且第一个元素没有块返回的“普通”数组时,差异才有意义,因此像empty?方法一样,复杂度仍为O(1)
David科斯塔

4

我建议使用unlessblank检查是否为空。

范例:

unless a.blank?
  a = "Is not empty"
end

这将知道“ a”为空还是不为空。如果“ a”为空白,则以下代码将无法运行。


4
#blank?是Rails的一部分。如果他们已经在使用Rails,无论如何#present?都是否定的#blank?
伊娃(Eva)

0

我不觉得不好用 any?。我经常使用。简洁明了。

但是,如果您担心所有nil值都将其抛出,那么您实际上是在问数组是否具有size > 0。在这种情况下,这种简单的扩展(未优化,猴子风格)会让您接近。

Object.class_eval do

  def size?
    respond_to?(:size) && size > 0
  end

end

> "foo".size?
 => true
> "".size?
 => false
> " ".size?
 => true
> [].size?
 => false
> [11,22].size?
 => true
> [nil].size?
 => true

这是相当描述性的,在逻辑上问“这个对象有大小吗?”。简洁明了,不需要ActiveSupport。而且很容易建立。

需要考虑的一些其他因素:

  1. 这不一样 present?来自ActiveSupport的不同。
  2. 您可能需要一个自定义版本 String,它会忽略空格(就像present?这样)。
  3. 您可能想要这个名字 length?String或其他类型以便于描述。
  4. 您可能希望将其定制为Integer和其他Numeric类型,以使逻辑零返回false
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.