ตรวจสอบว่าตัวแปรไม่เป็นศูนย์และไม่เป็นศูนย์ในทับทิม


271

ฉันใช้รหัสต่อไปนี้เพื่อตรวจสอบว่าตัวแปรไม่เป็นศูนย์หรือไม่เป็นศูนย์

if(discount != nil && discount != 0) 
  ...
end

มีวิธีที่ดีกว่าในการทำเช่นนี้?


1
อาจจะเป็นเพราะมันเป็นสำเนาถูกต้องของstackoverflow.com/questions/209495/...
David Nehme

1
มันควรทำอย่างไรถ้าdiscountเป็นเท็จ?
Andrew Grimm

1
ฉันคิดว่าdiscount.in? [0, nil]เป็นวิธีที่สะอาดกว่าที่เป็นไปได้
intmarinoreturn0

คำตอบ:


428
เว้นแต่จะมีส่วนลด || ส่วนลด == 0
  # ...
ปลาย

31
ใช้ 'หรือ' แทน ||
Orion Edwards

93
@ orion-edwards ทำไม?
NARKOZ

39
การใช้ 'หรือ' เป็นอันตราย 'หรือ' มีการแสดงตนของโอเปอเรเตอร์ที่ต่ำกว่า '=' ดังนั้นสิ่งต่อไปนี้มีพฤติกรรมที่ไม่คาดคิด: a = false หรือ true #a เป็นเท็จหลังจากข้อความนี้
Tom G

20
@xiy ปัจจุบันคำแนะนำแนะนำการเสแสร้งหรือและและไม่มีอยู่ (|| นั่นคือหรือ && &?)
3125280

67
ปัจจุบัน "ทับทิมคู่มือ Style" The and and or keywords are banned. It's just not worth it. Always use && and || instead.ยืน และมันก็ถูกต้องด้วยเหตุผลของเดวิดและทอม
Andre Figueiredo

40
class Object
  def nil_zero?
    self.nil? || self == 0
  end
end

# which lets you do
nil.nil_zero? # returns true
0.nil_zero?   # returns true
1.nil_zero?   # returns false
"a".nil_zero? # returns false

unless discount.nil_zero?
  # do stuff...
end

ระวังการปฏิเสธความรับผิดชอบตามปกติ ... พลังอันยิ่งใหญ่ / ความรับผิดชอบการปะลิงที่นำไปสู่ด้านมืด ฯลฯ


28

ตกลงหลังจาก 5 ปีผ่านไป ....

if discount.try :nonzero?
  ...
end

เป็นสิ่งสำคัญที่จะต้องทราบว่าtryมีการกำหนดไว้ในอัญมณี ActiveSupport ดังนั้นจึงไม่สามารถใช้ได้ในทับทิมธรรมดา


7
โปรดทราบว่านี่เป็นคำตอบเฉพาะสำหรับราง วานิลลาทับทิมไม่มีtryวิธี
Tom Lord

แก้ไข. แม้ว่ามันจะเป็นเหมือน ActiveSupport-specific มากขึ้นซึ่งเป็นการพึ่งพาและใช้กันอย่างแพร่หลายที่เบากว่ารางแบบเต็ม อย่างไรก็ตามตอนนี้การตอบสนองของ @ ndn เป็นสิ่งที่ถูกต้อง
เขียนใหม่

แก้ไขเพื่อใช้การนำทางอย่างปลอดภัย
เขียนใหม่

1
คำตอบตอนนี้ทำซ้ำstackoverflow.com/a/34819818/1954610 ... ฉันคิดว่ามีค่าที่จะปล่อยให้มันtryแสดงตัวเลือกอื่น (นี่คือเหตุผลว่าทำไม upvoted ตั้งแต่แรก!) ตราบใดที่ชัดเจน ผู้อ่านที่ActiveSupportไม่ใช่ทับทิมวานิลลา
ทอมลอร์ด

ชี้ไปที่คำตอบย้อนกลับ
เขียนใหม่

27
ยกเว้น [nil, 0] .include (ลดราคา) 
  # ...
ปลาย

13
สวย? ใช่. สามารถอ่านได้? ไม่ได้จริงๆ
El Ninja Trepador

1
ฉันพบว่าสิ่งนี้สามารถอ่านได้อย่างสมบูรณ์แบบและฉันต้องการมันมากกว่าคลาสใหม่ ทำได้ดี.
colincr

วิธี rubyist ที่สุดในการจัดการสองเงื่อนไข
Yugendran

23

จากทับทิม 2.3.0 เป็นต้นไปคุณสามารถรวมผู้ประกอบการนำทางที่ปลอดภัย ( &.) Numeric#nonzero?ด้วย &.ส่งคืนnilถ้าอินสแตนซ์เคยเป็นnilและnonzero?- ถ้าจำนวนเดิมคือ0:

if discount&.nonzero?
  # ...
end

หรือ postfix:

do_something if discount&.nonzero?

"foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String.... สิ่งนี้ไม่ปลอดภัยที่จะใช้กับวัตถุใด ๆ
ทอมลอร์ด

2
@ TomLord ตามที่ระบุไว้ในความคิดเห็นก่อนหน้านี้ไม่ได้มีวัตถุประสงค์เพื่อทำงานกับวัตถุโดยพลการ แทนที่จะเกี่ยวข้องกับกรณีเมื่อคุณมีบางสิ่งที่คุณรู้ว่าควรเป็นตัวเลข แต่อาจเป็นnilเช่นนั้น
ndnenkov

ฉันจะทำให้ความจริงนั้นชัดเจนในคำตอบมากกว่าที่จะมีคนอ่านแบบนี้และไม่สังเกตเห็นข้อจำกัดความรับผิดชอบในความคิดเห็น
Tom Lord

@TomLord มันเป็นที่ที่ระบุไว้ในคำตอบ" nonzero?- ถ้าตัวเลขเป็น0 " นอกจากนี้ยังจำเป็นที่จะต้องตรวจสอบว่าวัตถุพลสมบูรณ์เกิดขึ้นไม่ค่อยมากเมื่อเทียบกับการตรวจสอบตัวเลขที่อาจจะหรืออาจจะไม่0 nilดังนั้นมันจึงมีความหมายโดยนัย แม้ว่าจะมีใครบางคนทำให้สมมติฐานตรงกันข้ามพวกเขาจะเข้าใจได้ทันทีว่าเกิดอะไรขึ้นเมื่อพยายามดำเนินการ
ndnenkov


15

คุณสามารถทำได้:

if (!discount.nil? && !discount.zero?)

คำสั่งซื้อมีความสำคัญที่นี่เพราะถ้าdiscountเป็นnilเช่นนั้นจะไม่มีzero?วิธีการ การประเมินการลัดวงจรของรูบี้ควรป้องกันมิให้พยายามประเมินdiscount.zero?อย่างไรก็ตามหากdiscountเป็นnilเช่นนั้น


11

คุณสามารถแปลงแถวที่ว่างเปล่าของคุณเป็นค่าจำนวนเต็มและตรวจสอบศูนย์ได้หรือไม่

"".to_i.zero? => true
nil.to_i.zero? => true

ระวัง: 0.1.to_i == 0
Simon B.


2

คุณสามารถใช้ประโยชน์จากวิธีการที่NilClassมีให้#to_iซึ่งจะส่งกลับค่าศูนย์nil:

unless discount.to_i.zero?
  # Code here
end

หากdiscountสามารถเป็นเศษส่วนคุณสามารถใช้#to_fแทนเพื่อป้องกันการปัดเศษให้เป็นศูนย์


นี่ไม่ใช่คำตอบของ @ oivoodo ใช่ไหม
Cary Swoveland

ไม่ทำงานกับวัตถุใด ๆ "".to_i == "foo".to_i == "0".to_i == 0. วิธีการของคุณจะทำการข่มขู่ประเภทโดยไม่ตั้งใจทุกประเภท นอกจากนี้ยังจะล้มเหลวด้วยNoMethodErrorถ้าไม่ตอบสนองต่อdiscount to_i
Tom Lord

2
def is_nil_and_zero(data)
     data.blank? || data == 0 
end  

ถ้าเราผ่าน "" มันจะคืนค่าเท็จในขณะที่ว่างเปล่า ผลตอบแทนจริง เป็นกรณีเดียวกันเมื่อ data = false ว่างเปล่า? คืนค่าจริงสำหรับ nil, false, empty หรือสตริงช่องว่าง ดังนั้นจะดีกว่าถ้าใช้เปล่า? วิธีการเพื่อหลีกเลี่ยงสตริงว่างเช่นกัน


1
blank?เป็นวิธีเฉพาะทางรถไฟและไม่สามารถใช้ได้ในวานิลลาทับทิม
Tom Lord

คุณถูก!! ฉันคิดว่านี่เกี่ยวข้องกับแท็ก "ror" ดังนั้นจึงโพสต์ที่นี่ ความผิดพลาดของฉัน. นี่จะไม่ทำงานในวานิลลาทับทิม
Saroj

1

เมื่อจัดการกับบันทึกฐานข้อมูลฉันต้องการเริ่มต้นค่าว่างทั้งหมดด้วย 0 โดยใช้ผู้ช่วยการโยกย้าย:

add_column :products, :price, :integer, default: 0

0

คุณสามารถเริ่มต้นส่วนลดเป็น 0 ได้หากรหัสของคุณรับประกันว่าจะไม่ลองใช้ก่อนที่จะเริ่มต้น ที่จะลบหนึ่งเช็คฉันคิดว่าฉันไม่สามารถคิดอะไรอีก



0

ฉันชอบใช้วิธีที่สะอาดกว่า:

val.to_i.zero?

val.to_iจะกลับ0ถ้าValเป็นnil,

หลังจากนั้นสิ่งที่เราต้องทำคือตรวจสอบว่าค่าสุดท้ายเป็นศูนย์หรือไม่


-1

ทางเลือกอื่นคือใช้การปรับแต่งเช่น:

module Nothingness
  refine Numeric do
    alias_method :nothing?, :zero?
  end

  refine NilClass do
    alias_method :nothing?, :nil?
  end
end

using Nothingness

if discount.nothing?
  # do something
end

-7

ฉันเชื่อว่าต่อไปนี้ดีพอสำหรับรหัสทับทิม ฉันไม่คิดว่าฉันสามารถเขียนการทดสอบหน่วยที่แสดงความแตกต่างระหว่างสิ่งนี้กับแบบดั้งเดิม

if discount != 0
end

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