Неправильно ли проверить, что массив не пуст, используя метод any?
?
a = [1,2,3]
a.any?
=> true
a.clear
a.any?
=> false
Или лучше использовать unless a.empty?
?
Неправильно ли проверить, что массив не пуст, используя метод any?
?
a = [1,2,3]
a.any?
=> true
a.clear
a.any?
=> false
Или лучше использовать unless a.empty?
?
any?
в некоторых случаях не совпадает с not empty?
.
>> [nil, 1].any?
=> true
>> [nil, nil].any?
=> false
Из документации:
Если блок не указан, добавляет Ruby неявный блок {| obj | obj} (что любой? вернет true, если хотя бы один из членов коллекции не false или nil).
Метод 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
Префикс выражения с восклицательным знаком даст вам знать, не массив ли пуст. Итак, в вашем случае -
a = [1,2,3]
!a.empty?
=> true
Избегайте 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;
}
Я предлагаю использовать unless
и blank
для проверки пустым или нет.
Пример:
unless a.blank?
a = "Is not empty"
end
Это будет знать "a" пустое или нет. Если "a" пуст, то приведенный ниже код не будет работать.
Я не думаю, что использовать 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
.