Có một sự đối lập bao gồm? cho Mảng Ruby?


190

Tôi đã có logic sau trong mã của mình:

if !@players.include?(p.name)
  ...
end

@playerslà một mảng. Có một phương pháp để tôi có thể tránh !?

Lý tưởng nhất, đoạn trích này sẽ là:

if @players.does_not_include?(p.name)
  ...
end

1
doruby hợp lệ? tôi gặp lỗi syntax error, unexpected end-of-input(hoạt động nếu tôi xóa do)
maxymoo

Xem stackoverflow.com/a/60404934/128421 để biết điểm chuẩn cho việc tìm kiếm một mảng so với một tập hợp.
Tin Man

Câu trả lời:


369
if @players.exclude?(p.name)
    ...
end

ActiveSupport thêm exclude?phương pháp để Array, HashString. Đây không phải là Ruby nguyên chất, nhưng được sử dụng bởi rất nhiều người chơi ruby.

Nguồn: Phần mở rộng lõi hỗ trợ hoạt động (Hướng dẫn Rails)



3
Nhận xét nhỏ: AS thêm nó vào Enumerable để bạn có thể sử dụng nó với tất cả các lớp bao gồm Enumerable. Ngay cả với Hash. :)
user2422869

1
Đây là màu xanh lá cây được đánh dấu
etlds

Phương thức không còn được tải tự động trong Rails 4.2.3 (và có thể sớm hơn), bạn sẽ cầnrequire 'active_support/core_ext/enumerable'
Dennis

96

Ở đây bạn đi:

unless @players.include?(p.name)
  ...
end

Bạn có thể xem Hướng dẫn về Phong cách Ruby để biết thêm thông tin về các kỹ thuật tương tự.


Upvote cho hướng dẫn phong cách. Chỉ cần tài liệu đọc tôi cần.
justnorris

1
có thể đọc được cho một tuyên bố. Nếu nhiều thì tốt hơn nên dùng phủ định! hoặc thêm phương thức của riêng bạn vào lớp mảng ruby.
Đổi mới Sirotins

3
Thích điều này để loại trừ? Trả lời như Ruby thuần túy.
DScher

1
Nhưng vẫn kỳ lạ khi làm việc với một điều kiện ghép. if flag unless @players.include?(p.name)là vụng về và if flag && !@players.include?(p.name)sử dụng phủ định.
gabe

1
Trong khi ifchỉ để truevượt qua điều kiện, hãy unlessvượt qua falsenil. Điều này đôi khi dẫn đến khó tìm lỗi. Do đó tôi thíchexclude?
ToTenMilan

12

Làm thế nào về những điều sau đây:

unless @players.include?(p.name)
  ....
end

Man, với tốc độ mà câu trả lời xuất hiện trên trang web này, tôi không biết liệu tôi có nhận được bất kỳ danh tiếng nào mà không có chủ nghĩa gia đình tốt không! :-D Liên kết Hướng dẫn Phong cách là một liên lạc tốt đẹp.
ilasno

2
Nó không phải là về việc nhanh chóng. Đó là về sự kỹ lưỡng. (Tôi đã tìm thấy) =)
Charles Caldwell

11

Chỉ nhìn vào Ruby:

TL; DR

Sử dụng none?vượt qua nó một khối ==để so sánh:

[1, 2].include?(1)
  #=> true
[1, 2].none? { |n| 1 == n  }
  #=> false

Array#include?chấp nhận một đối số và sử dụng ==để kiểm tra đối với từng phần tử trong mảng:

player = [1, 2, 3]
player.include?(1)
 #=> true

Enumerable#none?cũng có thể chấp nhận một đối số trong trường hợp nó sử dụng ===để so sánh. Để có được hành vi đối nghịch với include?chúng ta bỏ qua tham số và truyền cho nó một khối sử dụng ==để so sánh.

player.none? { |n| 7 == n }
 #=> true 
!player.include?(7)    #notice the '!'
 #=> true

Trong ví dụ trên chúng ta thực sự có thể sử dụng:

player.none?(7)
 #=> true

Đó là bởi vì Integer#==Integer#===là tương đương. Nhưng hãy xem xét:

player.include?(Integer)
 #=> false
player.none?(Integer)
 #=> false

none?trả về falseInteger === 1 #=> true. Nhưng thực sự là một notinclude?phương pháp hợp pháp nên trở lại true. Vì vậy, như chúng tôi đã làm trước đây:

player.none? { |e| Integer == e  }
 #=> true

7
module Enumerable
  def does_not_include?(item)
    !include?(item)
  end
end

Ok, nhưng nghiêm túc, trừ khi hoạt động tốt.


1
+1 unlesskhông sao cho đoạn trích được hiển thị, nhưng điều kiện có thể phức tạp hơn. Tôi nghĩ thật tiện lợi khi có các phương thức phủ định này, chúng cho phép nhiều mã khai báo hơn.
tokland


1

Bạn có thể sử dụng:

unless @players.include?(p.name) do
...
end

unlessngược lại if, hoặc bạn có thể sử dụng reject.

Bạn có thể rejectcác yếu tố không bắt buộc:

@players.reject{|x| x==p.name}

sau khi nhận được kết quả, bạn có thể thực hiện.


0

Sử dụng unlesslà tốt cho các câu lệnh với include?các mệnh đề đơn , nhưng, ví dụ, khi bạn cần kiểm tra sự bao gồm của một cái gì đó Arraynhưng không phải trong một cái khác, thì việc sử dụng include?với exclude?sẽ thân thiện hơn nhiều.

if @players.include? && @spectators.exclude? do
  ....
end

Nhưng như dizzy42 đã nói ở trên, việc sử dụng exclude?yêu cầu ActiveSupport


Nó chỉ cần sử dụng Tiện ích mở rộng cốt lõi của Active Support. guide.rubyonrails.org/v3.2/
Người đàn ông Tin

0

Hãy thử một cái gì đó như thế này:

@players.include?(p.name) ? false : true

0

Hãy thử điều này, đó là Ruby thuần túy nên không cần thêm bất kỳ khung ngoại vi nào

if @players.include?(p.name) == false do 
  ...
end

Tôi đã vật lộn với một logic tương tự trong vài ngày, và sau khi kiểm tra một số diễn đàn và bảng hỏi đáp, nhưng hóa ra giải pháp thực sự khá đơn giản.


0

Tôi đã tìm kiếm điều này cho bản thân mình, tìm thấy điều này, và sau đó là một giải pháp. Mọi người đang sử dụng các phương pháp khó hiểu và một số phương pháp không hoạt động trong một số tình huống nhất định hoặc hoàn toàn không.

Tôi biết bây giờ đã quá muộn, vì điều này đã được đăng 6 năm trước, nhưng hy vọng khách truy cập trong tương lai tìm thấy điều này (và hy vọng, nó có thể dọn sạch mã của họ và của bạn.)

Giải pháp đơn giản:

if not @players.include?(p.name) do
  ....
end
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.