Відповіді:
any?
не те саме, що not empty?
в деяких випадках.
>> [nil, 1].any?
=> true
>> [nil, nil].any?
=> false
З документації:
Якщо блок не заданий, Ruby додає неявний блок {| obj | obj} (це будь-яке? повернеться істинним, якщо принаймні один із членів колекції не відповідає дійсності).
present?
методом оформлення замовлення .
#present?
- це лише Рейки. У чистому Ruby ви отримаєте NoMethodError: undefined method 'present?' for Array
.
require 'activesupport'
.
true
або якщо він порожній.Метод empty?
походить з класу Array
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F
Він використовується для перевірки, чи містить масив щось чи ні. Сюди входять речі, які оцінюються false
, такі як nil
і false
.
>> a = []
=> []
>> a.empty?
=> true
>> a = [nil, false]
=> [nil, false]
>> a.empty?
=> false
>> a = [nil]
=> [nil]
>> a.empty?
=> false
Метод any?
походить від модуля «Численні».
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F
Він використовується для оцінки, чи "будь-яке" значення в масиві оцінюється на 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
Префіксація висловлювання знаком оклику дасть вам знати, чи масив не порожній. Тож у вашому випадку -
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;
}
Різниця актуальна, якщо у вас є "розріджені" масиви, які починаються з великої кількості nil
значень, як, наприклад, щойно створений масив.
nil
значень, при "нормальних" масивах any?
без блоку повертається на першому елементі, тому складність все ще O (1), як empty?
метод
Я запропоную використовувати unless
та blank
перевірити, чи це порожньо чи ні.
Приклад:
unless a.blank?
a = "Is not empty"
end
Це знатиме "а" порожнє чи ні. Якщо "a" порожній, наведений нижче код не запускається.
#blank?
є частиною Rails. Якщо вони вже використовують Rails, #present?
це #blank?
все одно заперечення .
Я не думаю, що це взагалі погано використовувати 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
.
empty?
?