Toán tử điều kiện ( ? :
) được sử dụng trong Ruby như thế nào?
Ví dụ, điều này có đúng không?
<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>
Toán tử điều kiện ( ? :
) được sử dụng trong Ruby như thế nào?
Ví dụ, điều này có đúng không?
<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>
Câu trả lời:
Nó là toán tử ternary và nó hoạt động như trong C (không yêu cầu dấu ngoặc đơn). Đó là một biểu thức hoạt động như:
if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this
Tuy nhiên, trong Ruby, if
cũng là một biểu thức vì vậy: if a then b else c end
=== a ? b : c
, ngoại trừ các vấn đề ưu tiên. Cả hai đều là biểu thức.
Ví dụ:
puts (if 1 then 2 else 3 end) # => 2
puts 1 ? 2 : 3 # => 2
x = if 1 then 2 else 3 end
puts x # => 2
Lưu ý rằng trong trường hợp đầu tiên, bắt buộc phải có dấu ngoặc đơn (nếu không thì Ruby bị nhầm lẫn vì nó nghĩ rằng nó puts if 1
có thêm một số rác sau đó), nhưng chúng không được yêu cầu trong trường hợp cuối cùng vì vấn đề đã nói không phát sinh.
Bạn có thể sử dụng biểu mẫu "long-if" để dễ đọc trên nhiều dòng:
question = if question.size > 20 then
question.slice(0, 20) + "..."
else
question
end
nil
và false
. Thật ra không bình thường lắm.
puts true ? "true" : "false"
=> "true"
puts false ? "true" : "false"
=> "false"
puts (true ? "true" : "false")
với dấu ngoặc đơn. Nếu không thì thứ tự hoạt động không rõ ràng. Khi tôi lần đầu tiên đọc nó, tôi đã bối rối khi tôi đọc nó và (puts true) ? "true" : "false"
sau đó dự kiến sẽ puts
trả về boolean mà sau đó trở thành giá trị chuỗi.
Việc bạn sử dụng ERB cho thấy bạn đang ở trong Rails. Nếu vậy, hãy xem xét truncate
, một người trợ giúp tích hợp sẽ thực hiện công việc cho bạn:
<% question = truncate(question, :length=>30) %>
@pst đã đưa ra một câu trả lời tuyệt vời, nhưng tôi muốn đề cập rằng trong Ruby, toán tử ternary được viết trên một dòng là chính xác về mặt cú pháp, không giống như Perl và C nơi chúng ta có thể viết nó trên nhiều dòng:
(true) ? 1 : 0
Thông thường, Ruby sẽ phát sinh lỗi nếu bạn cố gắng phân chia nó thành nhiều dòng, nhưng bạn có thể sử dụng \
biểu tượng tiếp tục dòng ở cuối dòng và Ruby sẽ rất vui:
(true) \
? 1 \
: 0
Đây là một ví dụ đơn giản, nhưng nó có thể rất hữu ích khi xử lý các dòng dài hơn vì nó giữ cho mã được đặt ra độc đáo.
Cũng có thể sử dụng ternary mà không có các ký tự tiếp tục dòng bằng cách đặt các toán tử cuối cùng trên dòng, nhưng tôi không thích hoặc đề nghị nó:
(true) ?
1 :
0
Tôi nghĩ rằng điều đó dẫn đến việc thực sự khó đọc mã khi kiểm tra có điều kiện và / hoặc kết quả lâu hơn.
Tôi đã đọc những bình luận nói rằng không nên sử dụng toán tử ternary vì nó khó hiểu, nhưng đó là một lý do tồi để không sử dụng thứ gì đó. Theo cùng một logic, chúng ta không nên sử dụng các biểu thức chính quy, toán tử phạm vi (' ..
' và biến thể "flip-flop" dường như không xác định). Chúng mạnh mẽ khi được sử dụng đúng cách, vì vậy chúng ta nên học cách sử dụng chúng một cách chính xác.
Tại sao bạn đặt dấu ngoặc xung quanh
true
?
Hãy xem xét ví dụ của OP:
<% question = question.size > 20 ? question.question.slice(0, 20)+"..." : question.question %>
Kết thúc bài kiểm tra có điều kiện giúp làm cho nó dễ đọc hơn vì nó tách biệt trực quan bài kiểm tra:
<% question = (question.size > 20) ? question.question.slice(0, 20)+"..." : question.question %>
Tất nhiên, toàn bộ ví dụ có thể được thực hiện dễ đọc hơn bằng cách sử dụng một số bổ sung hợp lý của khoảng trắng. Điều này chưa được kiểm tra nhưng bạn sẽ có ý tưởng:
<% question = (question.size > 20) ? question.question.slice(0, 20) + "..." \
: question.question
%>
Hoặc, được viết nhiều hơn thành ngữ:
<% question = if (question.size > 20)
question.question.slice(0, 20) + "..."
else
question.question
end
%>
Thật dễ dàng để tranh luận rằng khả năng đọc cũng bị ảnh hưởng xấu question.question
.
true
?
true
thực sự đang ngồi trong những gì sẽ là một biểu thức đánh giá true
hoặc false
. Tốt hơn hết là phân định trực quan những cái đó vì các câu lệnh ternary có thể nhanh chóng chuyển thành nhiễu hình ảnh, làm giảm khả năng đọc ảnh hưởng đến khả năng bảo trì.
Một ví dụ đơn giản trong đó người vận hành kiểm tra xem id của người chơi có phải là 1 không và đặt id kẻ thù tùy thuộc vào kết quả
player_id=1
....
player_id==1? enemy_id=2 : enemy_id=1
# => enemy=2
Và tôi tìm thấy một bài viết về chủ đề này có vẻ khá hữu ích.
enemy_id = player_id == 1 ? 2 : 1
?
Mã condition ? statement_A : statement_B
tương đương với
if condition == true
statement_A
else
statement_B
end
Cách dễ nhất:
param_a = 1
param_b = 2
result = param_a === param_b ? 'Same!' : 'Not same!'
vì param_a
không bằng param_b
thì result
giá trị của nó sẽ làNot same!
question=question[0,20]
Nếu nó nhỏ hơn 20, nó sẽ không thay đổi nó.