Як зрозуміти нуль проти порожнього та порожнього в Рубі


1129

Я вважаю себе постійно шукаю чітке визначення відмінностей nil?, blank?і empty?в Ruby On Rails. Ось найближчий я прийшов:

  • blank?об'єкти - помилкові, порожні або рядок пробілів. Наприклад, "", " ", nil, [], і {}є порожніми.

  • nil? об'єкти - це екземпляри NilClass.

  • empty?об'єкти є специфічними для класу, і визначення змінюється від класу до класу. Рядок порожній, якщо в ньому немає символів, а масив порожній, якщо він не містить елементів.

Чи щось не вистачає, чи точнішого порівняння, яке можна зробити?


26
Один gotcha - це порожній масив, який повертає false для present?. Це тому, що blank?повертає true для порожнього масиву.
Кріс

4
Одна хороша річ , щоб побачити , що :nil?визначається на ::Kernelі перевизначена ::NilClass, в той час як :empty?здійснюється окремо від багатьох класів (спочатку на ::String, ::Array, ::Hash, і не рідний на інших класах , як ::Setвід STDLIB і ::ActiveRecord::Relationвід рейок). Таким чином, :nil?він доступний у всіх підкласах, ::Objectа також у кожному класі, що включає ::Kernelсам, де він :empty?повинен бути впроваджений або включений конкретно у ваші класи.
переписано

Якщо ви спробуєте зрозуміти всю nilконцепцію, починайте тут .
totymedli

[1] pry(main)> [].blank? => true
Майкл

Відповіді:


1437

.nil? може бути використаний на будь-якому об'єкті і є істинним, якщо об’єкт є нульовим.

.empty? може використовуватися для рядків, масивів та хешів та повертає true, якщо:

  • Довжина рядка == 0
  • Довжина масиву == 0
  • Довжина хеша == 0

Біг .empty?на щось, що є нульовим, кине а NoMethodError.

Ось де це .blank?входить. Він реалізований Rails і буде працювати на будь-якому об’єкті, а також працювати як .empty?на рядках, масивах і хешах.

nil.blank? == true
false.blank? == true
[].blank? == true
{}.blank? == true
"".blank? == true
5.blank? == false
0.blank? == false

.blank? також оцінює true на рядках, які не порожні, але містять лише пробіли:

"  ".blank? == true
"  ".empty? == false

Rails також забезпечує .present? , що повертає заперечення .blank?.

Матриця gotcha: blank?повернеться, falseнавіть якщо всі елементи масиву порожні. Для того, щоб визначити порожнечу в цьому випадку, використання all?з blank?, наприклад:

[ nil, '' ].blank? == false
[ nil, '' ].all? &:blank? == true 

27
Як було сказано в запитанні, деякі непусті рядки вважаються порожніми.
Ендрю Грімм

1
Чому вони не переписали нульові .порожні? якщо вони могли додати .blank?
до

6
Також:false.blank? == true
Шеннон

2
Я б зазначив presence!
Марк-Андре Лафортун

2
Як доповнення до всезапущеного масиву, який Том згадує у своїй відповіді, майте на увазі, що це може призвести до проблем безпеки, коли зловмисник може використовувати непідготовлений код, який просто перевіряє, хіба що params.nil? або якщо тільки params.blank ?, і це є причиною багато дискусій і роботи в даний час в Rails. Дивіться тут для отримання додаткової інформації: github.com/rails/rails/isissue/13420
Houen

675

Я зробив цю корисну таблицю з усіма справами:

введіть тут опис зображення

blank?, present?надаються Rails.


57
Слід зазначити, що порожнє? і присутній? є лише Рейки. Вони повертають виняток: NoMethodError в Ruby 2.0.0.
Lonny Everyus

17
Спробуйте додати, any?якщо ви коли-небудь оновлювати таблицю.
Денніс

blank?і present?не є лише " Rails ", вони автоматично включаються в Rails, але їх можна легко включити в код, який не містить Rails, використовуючи основні розширення ActiveSupport. Дивіться stackoverflow.com/questions/4238867/…
Олов'яний чоловік

215

Просто розгорніть стіл Джуліана:

введіть тут опис зображення

Посилання: порожній? Порожній? Нуль? 傻傻 分不清楚


1
@Sibevin Wang, я завантажив цю таблицю і використав її в деяких своїх відповідях, додавши вам кредити. Сподіваюсь, ви не заперечуєте :) Кудо до цього великого зусилля!
Лахіру

1
Enumerable#any?це ванільна Рубі, вона не повинна бути вказана у розділі "Тільки рейки"
daniero

1
@daniero Дякую за ваше нагадування, таблиця оновлюється.
Sibevin Wang

Числові типи також є .zero?і.nonzero?
DaveMongoose

63

Швидкий рада: !obj.blank? == obj.present?

Може бути зручним / легшим для очей у деяких виразах


є щось еквівалентне! obj.nil?
Кірк

present?є частиною active_support, перевірте тут, що потрібно включити, щоб отримати його: stackoverflow.com/a/4648704/1569
Фактор Mystic

2
@Kirk: !! obj еквівалентно! Obj.nil?
Мохаммед Хафез

4
@MohamedHafez Ні, це не так. !!false
Ajedi32

Ах, @ Ajedi32 хороший улов! еквівалент з цим одним винятком.
Мохамед Хафез

52

Одна відмінність полягає в тому, що це .nil?і .empty?є методи, які надаються мовою програмування Ruby, тоді як .blank?це щось, що додається рамкою веб-розробки Rails.


49

введіть тут опис зображення

  • Все, що nil?єblank?
  • Все, що empty?єblank?
  • Нічого, що empty?єnil?
  • Нічого, що nil?єempty?

tl; dr - використовуйте лише blank?, present?якщо ви не хочете розрізняти ""та" "


2
ваа! ви отримали мій +1
Am33d

16

Особливий випадок, коли намагаються оцінити, чи булеве значення дорівнює нулю:

false.present? == false
false.blank? == true
false.nil? == false

У цьому випадку рекомендується використовувати .nil?


14

Лише невелика примітка щодо any?рекомендації: Він правий, що це, як правило, рівнозначно !empty?. Однак any?повернемося trueдо рядка просто пробілу (ала" " ).

І звичайно, також дивіться коментар 1.9 вище.


У Rails будь-яка рядок, що містить просто символи пробілу, "порожній": "\ n \ r \ t" .пусто? # => вірно
Lonny Everyus

13

Не забувайте, any?що взагалі є !empty?. У Rails я, як правило, перевіряю наявність чогось у кінці заяви if somethingабо unless somethingпотім використовую blank?там, де потрібно, оскільки, здається, працює скрізь.


4
.any? не працює зі струнами в рубіні 1.9, як .anyany? вимагає нумерації, а рядок # кожен сам по собі не працює в рубіні 1.9.
Ендрю Грімм

4
Обережно ставимось any?до перевірки порожнечі. Він повертає помилковим, якщо у вас є масив хибних значень. Спосіб обійти це - пройти завжди справжній блок:, [nil, false].any?{ true }але !empty?він коротший, і ви не пам’ятаєте про дивну поведінку.
Кельвін

12

nil?- це стандартний метод Ruby, який можна викликати на всіх об'єктах і повертається, trueякщо об'єктом є nil:

b = nil
b.nil? # => true

empty?- це стандартний метод Ruby, який можна викликати на деяких об'єктах, таких як Strings, Arrays і Hashes, і повертається, trueякщо ці об'єкти не містять елемента:

a = []
a.empty? # => true

b = ["2","4"]
b.empty? # => false

empty? не можна закликати nil об'єкти.

blank?- метод Rails, який можна викликати як на nilоб'єктах, так і на порожніх об'єктах.


7

Всі інші добре пояснили, у чому різниця.

Я хотів би додати в Ruby On Rails, краще використовувати obj.blank?або obj.present?замість obj.nil?або obj.empty?.

obj.blank?обробляє всі типи nil, '', [], {}, і повертається , trueякщо значення не доступні і повертає , falseякщо значення доступні на будь-якому типі об'єкта.


5

exists?метод може бути використаний для перевірки існування даних у базі даних чи ні. Він повертає булеві значення trueабо false.


Працює лише на модельному класі!
Роджер

4

Рейки 4

альтернатива 'corray-brook' 'Array gotcha: blank?' перевірити, чи масив містить лише порожні значення і чи можна вважати порожнім? правда:

[ nil, '' ].all? &:blank? == true

можна також зробити:

[nil, '', "", " ",' '].reject(&:blank?).blank? == true

3

nil?може використовуватися на будь-якому об’єкті. Він визначає, чи має об'єкт якесь значення чи ні, включаючи "порожні" значення.

Наприклад:

example = nil
example.nil?  # true

"".nil?  # false

В основному nil?, коли-небудь повернеться істиною лише в тому випадку, якщо об'єкт насправді дорівнює "нулю".

empty?називається лише об'єктами, які вважаються колекцією. Сюди входять такі речі, як рядки (колекція символів), хеші (колекція пар ключів / значень) та масиви (колекція довільних об'єктів).empty?повертає істину, якщо в колекції немає елементів.

Наприклад:

"".empty? # true
"hi".empty?   # false
{}.empty?  # true
{"" => ""}.empty?   # false
[].empty?   # true
[nil].empty?  # false

nil.empty?  # NoMethodError: undefined method `empty?' for nil:NilClass

Зауважте це empty? не можна викликати об’єкти nil, оскільки об'єкти nil не є колекцією, і це призведе до виключення.

Також зауважте, що навіть якщо елементи в колекції порожні, це не означає, що колекція порожня.

blank?в основному є комбінацією, nil?і empty?це корисно для перевірки об'єктів, які, на вашу думку, є колекціями, але також можуть бути нульовими.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.