¿Hay un opuesto de incluir? para matrices de rubíes?

190

Tengo la siguiente lógica en mi código:

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

@playerses una matriz ¿Hay algún método para evitar el! ?

Idealmente, este fragmento sería:

if @players.does_not_include?(p.name)
  ...
end
Tyler DeWitt
fuente
1
es el dorubí válido? me sale un error syntax error, unexpected end-of-input(funciona si do
elimino
Consulte stackoverflow.com/a/60404934/128421 para obtener puntos de referencia para buscar una matriz frente a un conjunto.
El hombre de hojalata

Respuestas:

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

ActiveSupport agrega el exclude?método a Array, Hashy String. Esto no es Ruby puro, pero es usado por MUCHOS rubíes.

Fuente: Extensiones principales de soporte activo (guías de Rails)

mareado42
fuente
3
Comentario menor: AS lo agrega a Enumerable para que pueda usarlo con todas las clases que incluyen Enumerable. Incluso con Hash. :)
user2422869
1
Esto es debe ser verde marcado
etlds
El método ya no se carga automáticamente en Rails 4.2.3 (y posiblemente antes), deberá hacerlorequire 'active_support/core_ext/enumerable'
Dennis
96

Aqui tienes:

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

Puede echar un vistazo a la Guía de estilo Ruby para obtener más información sobre técnicas similares.

Bozhidar Batsov
fuente
Votación a favor de la guía de estilo. Solo el material de lectura que necesitaba.
justnorris
1
legible para una declaración. si muchos, entonces mejor usar negate! o agregue su propio método a la clase de matriz ruby.
Renars Sirotins
3
¿Prefieres esto a excluir? responde ya que es puro Ruby.
dscher
1
Pero sigue siendo extraño cuando se trabaja con una condición compuesta. if flag unless @players.include?(p.name)es incómodo y if flag && [email protected]?(p.name)usa la negación.
gabe
1
Mientras ifQue al menos truepasar la enfermedad, unlessdeja pasar falsey nil. Esto a veces conduce a errores difíciles de encontrar. Por eso prefieroexclude?
ToTenMilan
12

¿Qué tal lo siguiente:

unless @players.include?(p.name)
  ....
end
ilasno
fuente
Hombre, con la velocidad con la que entran las respuestas en este sitio, ¡no sé si voy a tener alguna reputación sin un buen nepotismo! :-D El enlace de la Guía de estilo es un buen toque.
ilasno
2
No se trata de ser rápido. Se trata de ser minucioso. (He encontrado) =)
Charles Caldwell
11

Mirando solo a Ruby:

TL; DR

Use none?pasarle un bloque con ==para la comparación:

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

Array#include?acepta un argumento y lo usa ==para verificar cada elemento de la matriz:

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

Enumerable#none?También puede aceptar un argumento en cuyo caso se utiliza ===para la comparación. Para obtener el comportamiento contrario include?, omitimos el parámetro y le pasamos un bloque usando ==para la comparación.

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

En el ejemplo anterior, podemos usar:

player.none?(7)
 #=> true

Eso es porque Integer#==y Integer#===son equivalentes. Pero considere:

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

none?vuelve falseporque Integer === 1 #=> true. Pero realmente notinclude?debería regresar un método legítimo true. Entonces, como lo hicimos antes:

player.none? { |e| Integer == e  }
 #=> true
Sagar Pandya
fuente
7
module Enumerable
  def does_not_include?(item)
    !include?(item)
  end
end

Ok, pero en serio, a menos que funcione bien.

Jesse Wolgamott
fuente
1
+1 unlessestá bien para el fragmento mostrado, pero la condición puede ser más compleja. Creo que es útil tener estos métodos negados, permiten más código declarativo.
tokland
2

Uso unless:

unless @players.include?(p.name) do
  ...
end
Mikita Belahlazau
fuente
1

Puedes usar:

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

unlesses opuesto a if, o puede usar reject.

Puede rejectlos elementos no requeridos:

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

después de obtener los resultados, puede hacer su implementación.

tekuri
fuente
0

El uso unlessestá bien para declaraciones con include?cláusulas únicas , pero, por ejemplo, cuando necesita verificar la inclusión de algo en una Arraypero no en otra, el uso de include?with exclude?es mucho más amigable.

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

Pero como dizzy42 dice anteriormente, el uso de exclude?requiere ActiveSupport

MeWillWork4Food
fuente
Solo necesita el uso de las extensiones principales de Active Support. guides.rubyonrails.org/v3.2/…
Tin Man
0

Intenta algo como esto:

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

Pruebe esto, es puro Ruby, por lo que no es necesario agregar ningún marco periférico

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

Estuve luchando con una lógica similar durante unos días, y después de revisar varios foros y tableros de preguntas y respuestas en vano, resultó que la solución era bastante simple.

KarmaDeli
fuente
0

Estaba buscando esto por mí mismo, encontré esto y luego una solución. Las personas usan métodos confusos y algunos métodos que no funcionan en ciertas situaciones o que no funcionan en absoluto.

Sé que es demasiado tarde ahora, teniendo en cuenta que esto se publicó hace 6 años, pero espero que los futuros visitantes encuentren esto (y con suerte, puede limpiar su código y el suyo).

Solución simple:

if not @players.include?(p.name) do
  ....
end
Voidableryzer
fuente