วิธีทำความเข้าใจกับค่าว่างเปล่าและค่าว่างใน Ruby


1129

ฉันพบตัวเองซ้ำ ๆ มองหาคำนิยามที่ชัดเจนของความแตกต่างของnil?, blank?และempty?ใน Ruby on Rails นี่คือสิ่งที่ฉันมาใกล้ที่สุด:

  • blank?วัตถุเป็นเท็จว่างหรือสตริงช่องว่าง ตัวอย่างเช่น"", " ", nil, []และ{}มีความว่างเปล่า

  • nil? วัตถุเป็นอินสแตนซ์ของ NilClass

  • empty?วัตถุเป็นคลาสเฉพาะและข้อกำหนดแตกต่างกันไปในแต่ละคลาส สตริงว่างเปล่าหากไม่มีตัวอักษรและอาร์เรย์จะว่างเปล่าหากไม่มีรายการ

มีอะไรที่ขาดหายไปหรือการเปรียบเทียบที่เข้มงวดกว่านี้สามารถทำได้หรือไม่?


26
หนึ่ง gotcha present?เป็นที่ว่างเปล่าเท็จผลตอบแทนอาร์เรย์ ซึ่งเป็นเพราะblank?ผลตอบแทนจริงสำหรับอาร์เรย์ที่ว่างเปล่า
กริช

4
สิ่งหนึ่งที่ดีคือจะเห็นว่า:nil?มีการกำหนดใน::Kernelและแทนที่ใน::NilClassขณะที่:empty?มีการใช้งานแยกกันในชั้นเรียนจำนวนมาก (natively บน::String, ::Array, ::Hashและไม่ใช่กำเนิดในชั้นเรียนอื่น ๆ เช่น::Setจาก STDLIB และ::ActiveRecord::Relationจากราง) ดังนั้น:nil?มีอยู่ในคลาสย่อยทั้งหมด::Objectและในทุกคลาสที่รวมอยู่::Kernelด้วยซึ่ง:empty?จะต้องนำไปใช้หรือรวมไว้ในคลาสของคุณโดยเฉพาะ
เขียนใหม่

ถ้าคุณพยายามที่จะเข้าใจทั้งnilแนวคิดเริ่มต้นที่นี่
totymedli

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

คำตอบ:


1437

.nil? สามารถใช้กับวัตถุใดก็ได้และเป็นจริงถ้าวัตถุนั้นเป็นศูนย์

.empty? สามารถใช้กับสตริงอาร์เรย์และแฮชและส่งคืนค่าจริงหาก:

  • ความยาวสตริง == 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?ซึ่งผลตอบแทนของการปฏิเสธ

Array gotcha: blank?จะส่งคืนfalseแม้ว่าองค์ประกอบทั้งหมดของอาร์เรย์จะว่างเปล่า ในการกำหนดความว่างเปล่าในกรณีนี้ให้ใช้all?กับblank?ตัวอย่างเช่น:

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

27
ดังที่กล่าวไว้ในคำถามสตริงที่ไม่ว่างบางตัวจะนับเป็นค่าว่าง
Andrew Grimm

1
ทำไมพวกเขาถึงไม่เขียนทับ. ว่างเปล่า? ถ้าพวกเขาสามารถเพิ่ม. ว่างเปล่า?
tillda

6
นอกจากนี้:false.blank? == true
แชนนอน

2
ฉันพูดถึงpresence!
Marc-André Lafortune

2
นอกเหนือจาก gotcha อาร์เรย์ว่างเปล่าทั้งหมดที่ Tom พูดถึงในคำตอบของเขาโปรดทราบว่าสิ่งนี้อาจนำไปสู่ปัญหาด้านความปลอดภัยที่ผู้โจมตีสามารถใช้รหัสที่ไม่ได้เตรียมตัวไว้ซึ่งตรวจสอบได้ง่าย ๆ ยกเว้นว่ามี params.nil? หรือเว้นเสียแต่ว่า params.blank? และเป็นสาเหตุของการสนทนาและการทำงานใน Rails ดูข้อมูลเพิ่มเติมได้ที่นี่: github.com/rails/rails/issues/13420
Houen

675

ฉันทำตารางที่มีประโยชน์นี้กับทุกกรณี:

ป้อนคำอธิบายรูปภาพที่นี่

blank?, present?ให้บริการโดยทางรถไฟ


57
ควรสังเกตว่าว่างเปล่า และปัจจุบัน เป็น Rails เท่านั้น พวกเขากลับมาข้อยกเว้น: NoMethodError ใน Ruby 2.0.0
Lonny Eachus

17
พิจารณาเพิ่มany?ถ้าคุณเคยปรับปรุงตาราง
เดนนิส

blank?และpresent?ไม่ใช่ " Rails-only " แต่จะรวมอยู่ใน Rails โดยอัตโนมัติ แต่สามารถรวมอยู่ในโค้ดที่ไม่ใช่ Rails ได้อย่างง่ายดายโดยใช้ส่วนขยายหลักของ ActiveSupport ดูstackoverflow.com/questions/4238867/…
Tin Man

215

เพียงขยายตารางของจูเลียน:

ป้อนคำอธิบายรูปภาพที่นี่

Ref: ว่างเปล่า? blank? nil? 傻傻分不清楚


1
@Sebevin Wang ฉันได้ดาวน์โหลดตารางนี้และใช้ในคำตอบของฉันเพิ่มเครดิตให้คุณ หวังว่าคุณจะไม่รังเกียจ :) ขอชื่นชมความพยายามอันยิ่งใหญ่นี้!
Lahiru

1
Enumerable#any?เป็น vanilla Ruby ไม่ควรอยู่ในรายการ "rails only"
daniero

1
@daniero ขอบคุณสำหรับการเตือนความจำของคุณตารางจะถูกอัพเดต
Sibevin Wang

ประเภทตัวเลขมี.zero?และ.nonzero?
DaveMongoose

63

เคล็ดลับด่วน: !obj.blank? == obj.present?

มีประโยชน์ / ง่ายต่อสายตาในบางสำนวน


มีอะไรที่เทียบเท่ากับ! obj.nil?
Kirk

present?เป็นส่วนหนึ่งของ active_support ตรวจสอบสิ่งที่จะรวมไว้ที่นี่: stackoverflow.com/a/4648704/1569
Factor Mystic

2
@ Kirk: !! obj เทียบเท่ากับ! obj.nil?
Mohamed Hafez

4
@MohamedHafez ไม่ไม่ !!false
Ajedi32

อ๊ะ @ Ajedi32 จับได้ดีเลย! เทียบเท่ากับข้อยกเว้นหนึ่งข้อ
Mohamed Hafez

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สู่สตริงของช่องว่าง (ala " ")

และแน่นอนดูที่ 1.9 ความคิดเห็นด้านบนด้วย


ใน Rails สตริงใด ๆ ที่ประกอบด้วยอักขระช่องว่างคือ "blank": "\ n \ r \ t" .blank? # => จริง
Lonny Eachus

13

อย่าลืมซึ่งโดยทั่วไปany? !empty?ใน Rails ฉันมักจะตรวจสอบว่ามีบางสิ่งอยู่ท้ายคำสั่งด้วยif somethingหรือunless somethingใช้blank?ที่จำเป็นเนื่องจากดูเหมือนว่าจะทำงานได้ทุกที่


4
.any? ใช้ไม่ได้กับสตริงใน ruby ​​1.9 เช่น. any? ต้องการนับจำนวนและสตริง # แต่ละตัวไม่ทำงานใน ruby ​​1.9
Andrew Grimm

4
ระมัดระวังany?ในการตรวจสอบความว่างเปล่า มันจะส่งกลับเท็จถ้าคุณมีอาร์เรย์ของค่าเท็จ วิธีที่จะหลีกเลี่ยงสิ่งนั้นได้คือการผ่านบล็อกที่เป็นจริงอยู่เสมอ: [nil, false].any?{ true }แต่!empty?จะสั้นกว่าและคุณจำพฤติกรรมแปลก ๆ ไม่ได้
Kelvin

12

nil?เป็นวิธีทับทิมมาตรฐานที่สามารถเรียกใช้บนวัตถุทั้งหมดและส่งคืนได้trueถ้าวัตถุคือnil:

b = nil
b.nil? # => true

empty?เป็นวิธี Ruby มาตรฐานที่สามารถเรียกใช้บนวัตถุบางอย่างเช่น Strings, Arrays และ HASH และส่งคืน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?สามารถใช้วิธีการตรวจสอบว่ามีข้อมูลอยู่ในฐานข้อมูลหรือไม่ ก็จะส่งกลับค่าบูลีนอย่างใดอย่างหนึ่งหรือtruefalse


ใช้งานได้กับคลาสรุ่นเท่านั้น!
Roger

4

ราง 4

ทางเลือกของ @ corban-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?ไม่สามารถเรียกใช้บนวัตถุใด ๆ ได้เนื่องจากวัตถุไม่มีการรวบรวมและมันจะยกข้อยกเว้น

โปรดสังเกตว่าแม้ว่ารายการในชุดสะสมจะว่างเปล่า แต่ก็ไม่ได้หมายความว่าชุดสะสมว่างเปล่า

blank?โดยพื้นฐานแล้วเป็นการรวมกันของnil?และempty?มันมีประโยชน์สำหรับการตรวจสอบวัตถุที่คุณคิดว่าเป็นคอลเลกชัน แต่อาจเป็นศูนย์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.