Jak rozumieć zero vs. pusta vs. pusta w Ruby


1129

Znalazłem się wielokrotnie szuka jasnego zdefiniowania różnic nil?, blank?oraz empty?w Ruby on Rails. Oto najbliższy, jaki przyszedłem:

  • blank?obiekty są fałszywe, puste lub zawierają spacje. Na przykład "", " ", nil, [], i {}są puste.

  • nil? obiekty są instancjami NilClass.

  • empty?obiekty są specyficzne dla klasy, a definicja różni się w zależności od klasy. Łańcuch jest pusty, jeśli nie ma znaków, a tablica jest pusta, jeśli nie zawiera żadnych elementów.

Czy brakuje czegoś lub dokładniejszego porównania?


26
Jedna gotcha to pusta tablica zwracająca wartość false present?. A to dlatego, że blank?zwraca wartość true dla pustej tablicy.
Kris,

4
Jedną miłą rzeczą jest to, aby zobaczyć, że :nil?jest określona na ::Kerneli nadpisane na ::NilClass, podczas gdy :empty?jest realizowany oddzielnie na wielu zajęciach (natywnie na ::String, ::Array, ::Hash, i nie natywnie w innych klasach, takich jak ::Setod stdlib oraz ::ActiveRecord::Relationz szyn). :nil?Jest więc dostępny we wszystkich podklasach, ::Objecta także we wszystkich klasach, które ::Kernelsame w sobie obejmują, gdzie :empty?należy je zaimplementować lub uwzględnić w swoich klasach.
przepisany

Jeśli spróbujesz zrozumieć całą nilkoncepcję, zacznij tutaj .
totymedli

[1] pry(main)> [].blank? => true
Michael

Odpowiedzi:


1437

.nil? może być używany na dowolnym obiekcie i jest prawdą, jeśli obiekt jest zerowy.

.empty? może być stosowany do ciągów, tablic i skrótów i zwraca wartość true, jeśli:

  • Długość łańcucha == 0
  • Długość tablicy == 0
  • Długość skrótu == 0

Bieganie .empty?na czymś zerowym rzuci NoMethodError.

W tym momencie .blank?pojawia się. Jest on implementowany przez Railsy i będzie działał na każdym obiekcie, a także będzie działał jak .empty?na ciągach, tablicach i skrótach.

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

.blank? sprawdza również wartość true dla ciągów, które nie są puste, ale zawierają tylko białe znaki:

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

Railsy również zapewniają .present? , co zwraca negację .blank?.

Tablica gotcha: blank?zwróci falsenawet jeśli wszystkie elementy tablicy są puste. Aby ustalić, pustka w tym przypadku korzystania all?z blank?, na przykład:

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

27
Jak wspomniano w pytaniu, niektóre niepuste ciągi liczą się jako puste.
Andrew Grimm,

1
Dlaczego nie zastąpią pustego pliku? gdyby mogli dodać .blank?
tillda

6
Również:false.blank? == true
Shannon,

2
Wspomniałbym presence!
Marc-André Lafortune

2
Jako dodatek do całkowicie pustej tablicy gotcha, o której Tom wspomina w swojej odpowiedzi, należy pamiętać, że może to prowadzić do problemów bezpieczeństwa, w których atakujący może użyć nieprzygotowanego kodu, który po prostu sprawdza, chyba że params.nil? lub chyba, że ​​params.blank ?, i jest przyczyną wielu dyskusji i pracy obecnie w Railsach. Zobacz tutaj, aby uzyskać więcej informacji: github.com/rails/rails/issues/13420
Houen

675

Zrobiłem tę przydatną tabelę ze wszystkimi przypadkami:

wprowadź opis zdjęcia tutaj

blank?, present?są dostarczane przez Rails.


57
Należy zauważyć, że puste? i obecny? są tylko Railsami. Zwracają wyjątek: NoMethodError w Ruby 2.0.0.
Lonny Eachus

17
Rozważ dodanie, any?jeśli kiedykolwiek zaktualizujesz tabelę.
Dennis

blank?i present?nie są „ tylko Railsami ”, są one automatycznie uwzględniane przez Railsy, ​​ale można je łatwo włączyć do kodu innego niż Railsy przy użyciu rozszerzeń Core ActiveSupport. Zobacz stackoverflow.com/questions/4238867/…
Tin Man

215

Po prostu przedłuż stół Juliana:

wprowadź opis zdjęcia tutaj

Ref: pusta? Pusta? Zerowa? 傻傻 分不清楚


1
@Sibevin Wang, pobrałem tę tabelę i wykorzystałem ją w niektórych moich odpowiedziach, dodając kredyty. Mam nadzieję, że nie będziesz miał nic przeciwko :) Chwała za ten wielki wysiłek!
Lahiru

1
Enumerable#any?jest waniliowy Ruby, nie należy go umieszczać w „tylko szynach”
daniero

1
@daniero Dziękujemy za przypomnienie, tabela została zaktualizowana.
Sibevin Wang

Typy liczbowe mają również .zero?i.nonzero?
DaveMongoose

63

Szybka wskazówka: !obj.blank? == obj.present?

Może być przydatny / łatwiejszy dla oczu w niektórych wyrażeniach


czy istnieje coś równoważnego z! obj.nil?
Kirk

present?jest częścią active_support, sprawdź tutaj, co należy zrobić, aby go zdobyć: stackoverflow.com/a/4648704/1569
Factor Mystic

2
@Kirk: !! obj jest równoważne z! Obj.nil?
Mohamed Hafez,

4
@MohamedHafez Nie, to nie jest. !!false
Ajedi32

Agh, @ Ajedi32 dobry połów! równoważne z tym jednym wyjątkiem.
Mohamed Hafez

52

Jedną różnicą jest to .nil? i .empty?są metodami, które są przewidziane przez język programowania Ruby, natomiast .blank?jest coś dodane przez framework Rails tworzenie stron internetowych.


49

wprowadź opis zdjęcia tutaj

  • Wszystko co jest nil? jestblank?
  • Wszystko co jest empty? jestblank?
  • Nic takiego nie jest empty?jestnil?
  • Nic takiego nie nil?jestempty?

tl; dr - używaj tylko blank?&, present?chyba że chcesz rozróżnić między ""i" "


2
Łał! dostałeś moje +1
Am33d

16

Szczególnym przypadkiem jest próba oceny, czy wartość logiczna wynosi zero:

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

W takim przypadku zaleca się użycie .nil?


14

Mała uwaga na temat any?zalecenia: ma rację, że ogólnie jest to odpowiednik !empty?. Jednak any?powróci truedo ciągu zaledwie spacji (ALA " ").

I oczywiście patrz też komentarz 1.9 powyżej.


W Railsach dowolny ciąg znaków zawierający tylko białe znaki jest „pusty”: „\ n \ r \ t” .blank? # => true
Lonny Eachus

13

Nie zapomnij, any?co jest ogólnie !empty?. W Railsach zazwyczaj sprawdzam obecność czegoś na końcu instrukcji za pomocą, if somethinga unless somethingnastępnie używam blank?tam, gdzie jest to potrzebne, ponieważ wydaje się, że działa wszędzie.


4
.każdy? nie działa z łańcuchami w Ruby 1.9, jak .any? wymaga wyliczenia, a ciąg # każdy sam w sobie nie działa w Ruby 1.9.
Andrew Grimm,

4
Ostrożnie any?sprawdzaj brak pustki. Zwraca false, jeśli masz tablicę wartości fałszowania. Sposobem na obejście tego jest ominięcie zawsze prawdziwego bloku: [nil, false].any?{ true }ale !empty?jest krótszy i nie pamiętasz dziwnego zachowania.
Kelvin

12

nil?jest standardową metodą Ruby, którą można wywoływać dla wszystkich obiektów i zwraca, truejeśli obiekt to nil:

b = nil
b.nil? # => true

empty?jest standardową metodą Ruby, którą można wywoływać dla niektórych obiektów, takich jak Strings, Arrays i Hashes, i zwraca, truejeśli te obiekty nie zawierają elementu:

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

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

empty? nie można wezwać nil obiektach.

blank?jest metodą Railsową, którą można wywoływać zarówno na nilobiektach, jak i pustych obiektach.


7

Wszyscy inni dobrze wyjaśnili, jaka jest różnica.

Chciałbym dodać Ruby On Rails, lepiej użyć obj.blank?lub obj.present?zamiast obj.nil?lubobj.empty? .

obj.blank?obsługuje wszystkie typy nil, '', [], {}, i powroty truejeśli wartości nie są dostępne i powroty falsejeżeli dostępne są na wszelkiego rodzaju obiektu wartości.


5

exists?Można użyć metody do sprawdzenia, czy dane istnieją w bazie danych, czy nie. Zwraca wartości logiczne albo truealbo false.


Działa tylko w klasie modeli!
Roger,

4

Szyny 4

alternatywa dla „Array gotcha: blank?” @ corban-brook do sprawdzania, czy tablice zawierają tylko puste wartości i czy można je uznać za puste? prawdziwe:

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

można również zrobić:

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

3

nil?może być używany na dowolnym obiekcie. Określa, czy obiekt ma jakąkolwiek wartość, czy nie, w tym wartości „puste”.

Na przykład:

example = nil
example.nil?  # true

"".nil?  # false

Zasadniczo nil?zwróci prawdę tylko wtedy, gdy obiekt jest w rzeczywistości równy „zero”.

empty?jest wywoływany tylko dla obiektów, które są uważane za kolekcję. Obejmuje to między innymi ciągi znaków (zbiór znaków), skróty (zbiór par klucz / wartość) i tablice (zbiór dowolnych obiektów). empty?zwraca true, jeśli nie ma żadnych elementów w kolekcji.

Na przykład:

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

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

Zauważ, że empty? nie można wywoływać obiektów zerowych, ponieważ obiekty zerowe nie są kolekcją i spowoduje to wyjątek.

Zauważ również, że nawet jeśli elementy w kolekcji są puste, nie oznacza to, że kolekcja jest pusta.

blank?jest w zasadzie kombinacją nil?i empty?Przydaje się do sprawdzania obiektów, które zakładamy, że są kolekcjami, ale mogą również być zerowe.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.