Tôi đang tìm kiếm một cách ngắn gọn để kiểm tra một giá trị để xem nó là 0 hay 0. Hiện tại tôi đang làm những việc như:
if (!val || val == 0)
# Is nil or zero
end
Nhưng điều này có vẻ rất vụng về.
Câu trả lời:
Đối tượng có một con số không? phương pháp .
if val.nil? || val == 0
[do something]
end
Hoặc, chỉ cho một hướng dẫn:
[do something] if val.nil? || val == 0
or
không yêu cầu bất kỳ parens nào ở đây và sẽ đọc hoàn toàn tự nhiên cho một Rubyist có kinh nghiệm. Những người duy nhất từng bị cắn ||
so với or
những người chưa bao giờ lập trình Perl :)
val && val == 0
là tốt hơn.
Nếu bạn thực sự thích tên phương thức có dấu chấm hỏi ở cuối:
if val.nil? || val.zero?
# do stuff
end
Giải pháp của bạn là tốt, cũng như một số giải pháp khác.
Ruby có thể khiến bạn tìm kiếm một cách hay để làm mọi thứ, nếu bạn không cẩn thận.
Từ Ruby 2.3.0 trở đi, bạn có thể kết hợp toán tử điều hướng an toàn ( &.
) với Numeric#nonzero?
. &.
trả về nil
nếu phiên bản là nil
và nonzero?
- nếu số là 0
:
unless val&.nonzero?
# Is nil or zero
end
Hoặc postfix:
do_something unless val&.nonzero?
unless val&.nonzero?
dịch để "nếu val là con số không hoặc không có"
do_something if val&.nonzero?
(hay còn gọi là nếu val
không nil
và không phải bằng không).
Trước hết, tôi nghĩ đó là cách ngắn gọn nhất mà bạn có thể kiểm tra tình trạng cụ thể đó.
Thứ hai, đối với tôi đây là mùi mã cho thấy một lỗ hổng tiềm ẩn trong thiết kế của bạn. Nói chung nil và 0 không có nghĩa giống nhau. Nếu có thể, bạn nên cố gắng loại bỏ khả năng val là nil trước khi bạn nhấn mã này, bằng cách kiểm tra điều đó ở đầu phương pháp hoặc một số cơ chế khác.
Bạn có thể có một lý do hoàn toàn chính đáng để làm điều này, trong trường hợp này, tôi nghĩ mã của bạn tốt, nhưng ít nhất tôi sẽ cân nhắc việc cố gắng loại bỏ kiểm tra nil nếu có thể.
Bạn có thể sử dụng Object.nil? để kiểm tra cụ thể nil (và không bị mắc kẹt giữa false và nil). Bạn cũng có thể vá một phương thức vào Object.
class Object
def nil_or_zero?
return (self.nil? or self == 0)
end
end
my_object = MyClass.new
my_object.nil_or_zero?
==> false
Điều này không được khuyến nghị vì các thay đổi đối với Đối tượng rất khó để đồng nghiệp theo dõi và có thể khiến mã của bạn không thể đoán trước được đối với người khác.
nil?
sẽ luôn trả về false. nil?
chỉ trả về true trên NilClass.
Object
, NilClass
và Numeric
. Object
sẽ trở lại false
, NilClass
sẽ trở lại true
và Numeric
sẽ trở lại zero?
.
nil.to_i trả về số không, vì vậy tôi thường làm điều này:
val.to_i.zero?
Tuy nhiên, bạn sẽ có một ngoại lệ nếu val là một đối tượng không phản hồi_to #to_i.
"5".to_i == 5, but you're more or less right. Clever but doesn't actually work
Tôi tin rằng mã của bạn không chính xác; nó sẽ trong thử nghiệm thực tế cho ba giá trị: nil
, false
, và zero. Điều này là do !val
biểu thức đúng với tất cả các giá trị sai, trong Ruby là nil
và false
.
Điều tốt nhất tôi có thể nghĩ ra ngay bây giờ là
if val == nil || val == 0
# do stuff
end
Tất nhiên là không thông minh lắm, nhưng (rất) rõ ràng.
Giải pháp của tôi cũng sử dụng Refinements, trừ đi các điều kiện.
module Nothingness
refine Numeric do
alias_method :nothing?, :zero?
end
refine NilClass do
alias_method :nothing?, :nil?
end
end
using Nothingness
if val.nothing?
# Do something
end
Rails thực hiện điều này thông qua các phương thức truy vấn thuộc tính, trong đó ngoài false và nil, 0 và "" cũng đánh giá thành false.
if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation
Tuy nhiên nó có phần của những lời gièm pha. http://www.joegrossberg.com/archives/002995.html
#attribute
, vì tôi không thể tìm thấy bất cứ điều gì giống như vậy.
Để trở nên thành ngữ nhất có thể, tôi đề nghị điều này.
if val.nil? or val == 0
# Do something
end
Bởi vì:
Ngắn gọn và rõ ràng
[0, nil].include?(val)
val.in? [0,nil]
Cách ngắn nhất và tốt nhất nên là
if val&.>(0)
# do something
end
Đối với val&.>(0)
nó trả về nil khi val là nil vì> về cơ bản cũng là một phương thức, nil bằng false trong ruby. Nó trả về false khi val == 0
.
Tôi giải quyết vấn đề này bằng cách xác định "là?" mà sau đó tôi có thể triển khai khác nhau trên các lớp khác nhau. Vì vậy, đối với Array, "là?" có nghĩa là "kích thước> 0"; đối với Fixnum nó có nghĩa là "self! = 0"; đối với String, nó có nghĩa là "self! = ''". NilClass, tất nhiên, định nghĩa "là?" như chỉ trả về con số không.
Bạn có thể sử dụng case
nếu bạn thích:
case val with nil, 0
# do stuff
end
Sau đó, bạn có thể sử dụng bất cứ thứ gì phù hợp với nó ===
, đôi khi điều này rất hay. Hoặc làm điều gì đó như sau:
not_valid = nil, 0
case val1 with *not_valid
# do stuff
end
#do other stuff
case val2 with *not_valid, false #Test for values that is nil, 0 or false
# do other other stuff
end
Nó không hẳn là OOP tốt, nhưng nó rất linh hoạt và hoạt động. Của tôi if
thường kết thúc là case
s dù sao.
Tất nhiên Enum.any?
/ Enum.include?
loại công việc quá ... nếu bạn muốn thực sự khó hiểu:
if [0, nil].include? val
#do stuff
end
Tất nhiên, điều đúng đắn cần làm là xác định một phương thức hoặc hàm. Hoặc, nếu bạn phải làm điều tương tự với nhiều giá trị, hãy sử dụng kết hợp các trình vòng lặp tốt đẹp đó.
Tôi thực sự thích Rails blank?
phương pháp cho rằng loại của sự vật, nhưng nó sẽ không trở về true
cho 0
. Vì vậy, bạn có thể thêm phương pháp của mình:
def nil_zero?
if respond_to?(:zero?)
zero?
else
!self
end
end
Và nó sẽ kiểm tra xem một số giá trị là 0 hay 0:
nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false
if val.nil_zero?
#...
end
Thay vì chắp vá một lớp, bạn có thể sử dụng các sàng lọc bắt đầu từ Ruby 2.1. Việc sàng lọc tương tự như việc vá khỉ; trong đó, chúng cho phép bạn sửa đổi lớp, nhưng việc sửa đổi bị giới hạn trong phạm vi bạn muốn sử dụng nó.
Điều này là quá mức cần thiết nếu bạn muốn thực hiện việc kiểm tra này một lần, nhưng nếu bạn đang lặp lại chính mình thì đó là một sự thay thế tuyệt vời cho việc vá khỉ.
module NilOrZero
refine Object do
def nil_or_zero?
nil? or zero?
end
end
end
using NilOrZero
class Car
def initialize(speed: 100)
puts speed.nil_or_zero?
end
end
car = Car.new # false
car = Car.new(speed: nil) # true
car = Car.new(speed: 0) # true
Các sàng lọc đã được thay đổi vào phút cuối để được đưa vào phạm vi tệp. Vì vậy, các ví dụ trước đó có thể đã cho thấy điều này, điều này sẽ không hoạt động.
class Car
using NilOrZero
end
Điều này rất ngắn gọn:
if (val || 0) == 0
# Is nil, false, or zero.
end
Nó hoạt động miễn là bạn không ngại đối xử false
giống như nil
. Trong các dự án tôi đã làm việc, sự khác biệt đó chỉ quan trọng đôi khi. Phần còn lại của thời gian cá nhân tôi thích bỏ qua .nil?
và có mã ngắn hơn một chút.
[ Cập nhật : Tôi không viết những thứ như thế này nữa. Nó hoạt động nhưng quá khó hiểu. Tôi đã cố gắng giải quyết những sai lầm của mình bằng cách thay đổi một vài chỗ mà tôi đã làm.]
Nhân tiện, tôi đã không sử dụng .zero?
vì điều này tạo ra một ngoại lệ nếu val
là một chuỗi. Nhưng .zero?
sẽ ổn nếu bạn biết không phải như vậy.
[edited]
Tôi nghĩ rằng nếu val
là nil thì biểu thức này sẽ đánh giá thành nil == 0
(và do đó trả về false
). Tuy nhiên, có vẻ như nó thực sự hoạt động, mặc dù tôi không nghĩ rằng nó rất dễ đọc.
Giải pháp khác:
if val.to_i == 0
# do stuff
end
"5".to_i == 5
, nhưng bạn ít nhiều đúng. Thông minh nhưng không thực sự hiệu quả.
val ||= 0
if val == 0
# do something here
end
val
cần được giữ lại thì sao? Bạn đang chặn dữ liệu đầu vào bằng phương pháp này và có những cách tốt hơn, ít phá hoại hơn để kiểm tra nil hay 0.
false
?