2010-04-08 15 views
20

Tengo dos matrices de Ruby, y necesito ver si tienen algún valor en común. Podría simplemente recorrer cada uno de los valores en una matriz y incluir?() En la otra, pero estoy seguro de que hay una mejor manera. ¿Qué es? (Las matrices tienen cadenas).¿Cómo puedo verificar si una matriz de Ruby incluye uno de varios valores?

Gracias.

+0

qué te importa lo que los elementos que tiene en común? – Levi

+0

No. Todo lo que quiero saber es si los dos tienen algún elemento en común. – Colen

Respuesta

65

Set intersect ellos:

a1 & a2 

He aquí un ejemplo:

> a1 = [ 'foo', 'bar' ] 
> a2 = [ 'bar', 'baz' ] 
> a1 & a2 
=> ["bar"] 
> !(a1 & a2).empty? # Returns true if there are any elements in common 
=> true 
+3

bueno, el OP quiere "verificar", por lo que un resultado booleano sería un mejor ajuste:! (A1 y a2) .empty? – tokland

+4

Iría con (a1 y a2) .any? en lugar de! (a1 y a2) .empty? – rilla

+1

@rilla 'any?' Funciona en este caso, pero no cuando se trata de valores 'false' y' nil': '[nil, false] .any? # => falso'. – Stefan

6

Cualquier valor en común? se puede utilizar el operador de cruce: &

[ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ] 

Si usted está buscando una intersección completa sin embargo (con duplicados) el problema es más complejo ya existe un desbordamiento de pila aquí: How to return a Ruby array intersection with duplicate elements? (problem with bigrams in Dice Coefficient)

O una rápida snippet que define "real_intersection" y valida la siguiente prueba

class ArrayIntersectionTests < Test::Unit::TestCase  
    def test_real_array_intersection 
    assert_equal [2], [2, 2, 2, 3, 7, 13, 49] & [2, 2, 2, 5, 11, 107] 
    assert_equal [2, 2, 2], [2, 2, 2, 3, 7, 13, 49].real_intersection([2, 2, 2, 5, 11, 107]) 
    assert_equal ['a', 'c'], ['a', 'b', 'a', 'c'] & ['a', 'c', 'a', 'd'] 
    assert_equal ['a', 'a', 'c'], ['a', 'b', 'a', 'c'].real_intersection(['a', 'c', 'a', 'd']) 
    end 
end 
3

El uso de la intersección se ve bien, pero es ineficaz. Yo usaría "¿alguno?" en la primera matriz (por lo que la iteración se detiene cuando uno de los elementos se encuentra en la segunda matriz). Además, el uso de un conjunto en el segundo conjunto hará que los controles de membresía sean rápidos. es decir .:

a = [:a, :b, :c, :d] 
b = Set.new([:c, :d, :e, :f]) 
c = [:a, :b, :g, :h] 

# Do a and b have at least a common value? 
a.any? {|item| b.include? item} 
# true 

# Do c and b have at least a common value? 
c.any? {|item| b.include? item} 
#false 
+1

La evaluación comparativa muestra que es 1,5-2 veces más rápido que el método de intersección de conjuntos (más estético), en función del valor simple frente a la comparación de atributos de objetos. Establecer intersección usando 'any?' En lugar de 'empty?', Como se sugiere en un comentario anterior, varió ligeramente, pero no cambió el resultado. (Estrictamente considerando el rendimiento, y como se esperaba ya que 'any?' Rescata en el primer partido). –

0

probar este

a1 = [ 'foo', 'bar' ] 
a2 = [ 'bar', 'baz' ] 
a1-a2 != a1 
true 
Cuestiones relacionadas