2010-04-08 12 views
20

J'ai deux tableaux Ruby, et j'ai besoin de voir s'ils ont des valeurs communes. Je pourrais simplement parcourir chacune des valeurs dans un tableau et inclure?() De l'autre, mais je suis sûr qu'il y a une meilleure façon de faire. Qu'Est-ce que c'est? (Les tableaux contiennent tous les deux des chaînes.)Comment puis-je vérifier si un tableau Ruby inclut une ou plusieurs valeurs?

Merci.

+0

-vous soin quels sont les éléments qu'il a en commun? – Levi

+0

Non. Tout ce que je veux savoir, c'est si les deux ont des éléments communs. – Colen

Répondre

65

Set intersect les:

a1 & a2 

Voici un exemple:

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

bien, l'OP veut "vérifier", donc un résultat booléen serait un meilleur ajustement:! (A1 & a2) .empty? – tokland

+4

J'irais avec (a1 & a2) .any? au lieu de! (a1 & a2) .empty? – rilla

+1

@rilla 'any?' Fonctionne dans ce cas, mais pas avec les valeurs 'false' et' nil': '[nil, false] .any? # => false'. – Stefan

6

Toute valeur en commun? vous pouvez utiliser l'opérateur d'intersection: &

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

Si vous êtes à la recherche d'une intersection complète cependant (avec doublons) le problème est plus complexe il y a déjà un débordement de pile ici: How to return a Ruby array intersection with duplicate elements? (problem with bigrams in Dice Coefficient)

Ou un snippet rapide qui définit "real_intersection" et valide le test suivant

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

L'utilisation d'une intersection semble agréable, mais inefficace. J'utiliserais "any?" sur le premier tableau (de sorte que l'itération s'arrête lorsque l'un des éléments est trouvé dans le second tableau). En outre, l'utilisation d'un ensemble sur le deuxième tableau rendra les vérifications d'adhésion rapides. i.e. .:

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

L'analyse comparative montre que cette méthode est 1,5 à 2 fois plus rapide que la méthode d'intersection définie (plus esthétique), en fonction de la comparaison entre la valeur simple et l'attribut d'objet. Définir l'intersection en utilisant 'any?' Au lieu de 'empty?', Comme suggéré dans un commentaire ci-dessus, a légèrement varié, mais n'a pas changé le résultat. (Considérant strictement la performance, et comme attendu depuis 'any?' Bails sur le premier match.) –

0

Essayez cette

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