Проверить, что массив не пуст: any?

Неправильно ли проверить, что массив не пуст, используя метод any??

a = [1,2,3]

a.any?
=> true

a.clear

a.any?
=> false

Или лучше использовать unless a.empty??

Ответ 1

any? в некоторых случаях не совпадает с not empty?.

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

Из документации:

Если блок не указан, добавляет Ruby неявный блок {| obj | obj} (что любой? вернет true, если хотя бы один из членов коллекции не false или nil).

Ответ 2

Разница между массивом, оценивающим его значения, значением true или его пустым.

Метод empty? поступает из класса Array
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F

Используется для проверки того, содержит ли массив что-то или нет. Сюда относятся вещи, которые оцениваются как ложные, такие как nil и false.

>> 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

Используется для оценки того, соответствуют ли "любые" значения в массиве true. Аналогичные методы для этого нет? все? и один? где все они просто проверяют, сколько раз можно было оценить истину. который не имеет никакого отношения к счету значений, найденных в массиве.

случай 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

Ответ 3

Префикс выражения с восклицательным знаком даст вам знать, не массив ли пуст. Итак, в вашем случае -

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

Ответ 4

Избегайте 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;
}

Ответ 5

Я предлагаю использовать unless и blank для проверки пустым или нет.

Пример:

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

Это будет знать "a" пустое или нет. Если "a" пуст, то приведенный ниже код не будет работать.

Ответ 6

Я не думаю, что использовать 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. И это легко построить.

Некоторые дополнительные возможности:

  • Это не то же самое, что present? из ActiveSupport.
  • Вам может понадобиться пользовательская версия для String, которая игнорирует пробелы (например, present?).
  • Вам может понадобиться имя length? для String или других типов, где это может быть более описательным.
  • Вы можете использовать его для Integer и других Numeric типов, так что логический нуль возвращает false.