Apakah ada kebalikan dari memasukkan? untuk Array Ruby?


190

Saya punya logika berikut dalam kode saya:

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

@playersadalah sebuah array. Apakah ada metode sehingga saya bisa menghindari itu !?

Idealnya, cuplikan ini adalah:

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

1
apakah doruby yang valid? saya mendapatkan kesalahan syntax error, unexpected end-of-input(berfungsi jika saya menghapus do)
maxymoo

Lihat stackoverflow.com/a/60404934/128421 untuk benchmark untuk mencari array vs. set.
the Tin Man

Jawaban:


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

ActiveSupport menambahkan exclude?metode untuk Array, Hash, dan String. Ini bukan Ruby murni, tetapi digunakan oleh BANYAK pembuat ruby.

Sumber: Ekstensi Inti Dukungan Aktif (Panduan Rails)



3
Komentar minor: AS menambahkannya ke Enumerable sehingga Anda dapat menggunakannya dengan semua kelas yang menyertakan Enumerable. Bahkan dengan Hash. :)
user2422869

1
Ini harus
ditandai

Metode ini tidak lagi dimuat secara otomatis di Rails 4.2.3 (dan mungkin sebelumnya), Anda harusrequire 'active_support/core_ext/enumerable'
Dennis

96

Ini dia:

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

Anda mungkin melihat Panduan Gaya Ruby untuk info lebih lanjut tentang teknik serupa.


Suara positif untuk panduan gaya. Hanya bahan bacaan yang saya butuhkan.
justnorris

1
dapat dibaca untuk satu pernyataan. jika banyak maka lebih baik gunakan negate! atau tambahkan metode Anda sendiri ke kelas array ruby.
Renars Sirotins

3
Lebih suka ini untuk dikecualikan? jawab karena itu murni Ruby.
Dscher

1
Namun tetap aneh ketika bekerja dengan kondisi majemuk. if flag unless @players.include?(p.name)canggung dan if flag && !@players.include?(p.name)menggunakan negasi.
gabe

1
Sementara ifbiarkan hanya truemelewati kondisi, unlessmari lewat falsedan nil. Ini kadang-kadang menyebabkan sulit untuk menemukan bug. Karena itu saya lebih sukaexclude?
ToTenMilan

12

Bagaimana dengan yang berikut:

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

Sobat, dengan kecepatan jawaban masuk di situs ini, saya tidak tahu apakah saya akan mendapatkan reputasi tanpa nepotisme yang bagus! :-D Tautan Panduan Gaya adalah sentuhan yang bagus.
ilasno

2
Ini bukan tentang menjadi cepat. Ini tentang menjadi menyeluruh. (Saya telah menemukan) =)
Charles Caldwell

11

Hanya melihat Ruby:

TL; DR

Gunakan none?melewatinya satu blok dengan ==untuk perbandingan:

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

Array#include?menerima satu argumen dan digunakan ==untuk memeriksa setiap elemen dalam array:

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

Enumerable#none?juga dapat menerima satu argumen yang digunakan ===untuk perbandingan. Untuk mendapatkan perilaku yang berlawanan, include?kami menghilangkan parameter dan memberikannya blok ==untuk perbandingan.

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

Dalam contoh di atas kita dapat menggunakan:

player.none?(7)
 #=> true

Itu karena Integer#==dan Integer#===setara. Tapi pertimbangkan:

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

none?kembali falsekarena Integer === 1 #=> true. Tetapi notinclude?metode yang benar-benar harus dikembalikan true. Seperti yang kami lakukan sebelumnya:

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

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

Ok, tapi serius, kecuali berfungsi dengan baik.


1
+1 unlesstidak apa-apa untuk cuplikan cuplikan, tetapi kondisinya mungkin lebih rumit. Saya pikir ini berguna untuk memiliki metode yang dinegasikan ini, mereka memungkinkan lebih banyak kode deklaratif.
tokland


1

Bisakah Anda menggunakan:

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

unlesskebalikan dari if, atau Anda dapat menggunakan reject.

Anda dapat rejectelemen yang tidak diperlukan:

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

setelah mendapatkan hasil Anda dapat melakukan implementasi Anda.


0

Menggunakan unlessbaik-baik saja untuk pernyataan dengan satu include?klausa tetapi, misalnya, ketika Anda perlu memeriksa dimasukkannya sesuatu dalam satu Arraytetapi tidak dalam yang lain, penggunaan include?dengan exclude?jauh lebih ramah.

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

Tetapi seperti yang dikatakan dizzy42 di atas, penggunaan exclude?membutuhkan ActiveSupport


Itu hanya perlu menggunakan Ekstensi Inti Dukungan Aktif. guide.rubyonrails.org/v3.2/…
the Tin Man

0

Coba sesuatu seperti ini:

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

0

Coba ini, ini murni Ruby sehingga tidak perlu menambahkan kerangka periferal

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

Saya berjuang dengan logika yang sama selama beberapa hari, dan setelah memeriksa beberapa forum dan papan Q&A sedikit berhasil ternyata solusinya sebenarnya cukup sederhana.


0

Saya mencari ini untuk diri saya sendiri, menemukan ini, dan kemudian solusi. Orang menggunakan metode yang membingungkan dan beberapa metode yang tidak berfungsi dalam situasi tertentu atau tidak sama sekali.

Saya tahu ini sudah terlambat sekarang, mengingat ini telah diposting 6 tahun yang lalu, tapi semoga pengunjung yang akan datang menemukan ini (dan mudah-mudahan, ini dapat membersihkan kode mereka, dan Anda.)

Solusi sederhana:

if not @players.include?(p.name) do
  ....
end
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.