2011-06-15 2 views
2

J'ai un tableau de tableaux, appelé guid_pairs:Ruby égalité de tableau

[['a','b','c'],['c','g'],['z','f','b']] 

J'ai aussi un tableau, appelé array_to_check:

['c','a','b'] 

Comment puis-je déterminer si le tableau guid_pairs a un élément c'est-à-dire array_to_check. L'égalité ne doit pas prendre en compte la position des éléments du tableau.

Dans cet exemple, le chèque doit retourner true car guid_pairs contient l'élément ['a','b','c'], qui correspond ['c','a','b'].

J'ai essayé, mais il semble toujours revenir false même quand il doit retourner true:

guid_pairs.any?{|pair| pair.eql?(array_to_check)} 

J'utilise Ruby 1.9.2

+4

On dirait que vous utilisez la structure de données erronées. Pensez à utiliser [sets] (http://ruby-doc.org/stdlib/libdoc/set/rdoc/index.html) à la place. –

Répondre

8

Il y a un set class dans la bibliothèque standard et en utilisant des ensembles correspond bien à votre intention:

require 'set' 

a = ['c','a','b'] 
aa = [['a','b','c'],['c','g'],['z','f','b']] 

find_this = Set.new(a) 
the_match = aa.find { |x| find_this == Set.new(x) } 

qui laissera l'élément d'élément correspondant de aa dans the_match. Si vous êtes seulement intéressé par l'existence alors vous pouvez simplement vérifier la véracité de the_match; ou utiliser any? (merci pour le rappel Michael Kohl, j'oublie souvent de quelques-unes des choses Enumerable):

aa.any? { |x| find_this == Set.new(x) } 

Pas de trucs, pas de magie, et en utilisant Set, il est clair que vous êtes, en fait, la comparaison les tableaux sous forme d'ensembles.


BTW, votre tentative de solution:

guid_pairs.any? { |pair| pair.eql?(array_to_check) } 

ne fonctionne pas parce que les tableaux comparent l'élément par élément pour si deux tableaux sont égaux si et seulement s'ils ont des éléments égaux dans la même commande. Le documentation for eql? pourrait être plus clair:

Renvoie true si l'auto et d'autres sont le même objet, ou sont les deux tableaux avec le même contenu.

Mais le == documentation est agréable et claire:

Deux tableaux sont égales si elles contiennent le même nombre d'éléments et si chaque élément est égal à l'élément correspondant (selon objet ==). dans l'autre tableau.

Nous pouvons chercher à Object#eql? des éclaircissements si:

Le eql? La méthode renvoie true si obj et anObject ont la même valeur. Utilisé par Hash pour tester les membres pour l'égalité. Pour les objets de la classe Object, eql? est synonyme de ==. Les sous-classes continuent normalement cette tradition, mais il y a des exceptions.

Alors == et eql? doit se comporter de la même façon moins qu'il y ait une bonne raison pour eux d'être différents.

+1

Vous pouvez utiliser 'any?' Au lieu de 'find' si vous ne vous souciez que de la vérité. +1 btw, car je préfère aussi les ensembles à cette fin. –

+0

@Michael: Merci pour le rappel. J'aime l'expressivité d'utiliser Set pour ce genre de chose, dis ce que tu veux dire et tout ça. –

1

Une solution possible consiste à trier les tableaux avant de comparaison (ou même pendant la comparaison):

guid_pairs.any?{|pair| pair.sort.eql?(array_to_check.sort)} 

Notez que cela peut ne pas être une solution - il serait plus approprié d'avoir votre un rrays triés (néanmoins ils sont des ensembles dans votre cas d'utilisation).

0

Vous pouvez utiliser les éléments suivants:

sorted_array_to_check = array_to_check.sort 
guid_pairs.any?{|pair| pair.sort.eql?(sorted_array_to_check)} 
0

Trois solutions:

class Array 
    def check1 other; other.any?{|e| self - e == e - self} end 
    def check2 other; other.any?{|e| self | e == self and e | self == e} end 
    def check3 other; other.any?{|e| self & e == self and e & self == e} end 
end 
array_to_check.check1(guid_pairs) # => true 
array_to_check.check2(guid_pairs) # => true 
array_to_check.check3(guid_pairs) # => true 

Sans définir une méthode (suite à la suggestion de Josha):

array_to_check.instance_eval{guid_pairs.any?{|e| self - e == e - self}} # => true 
    array_to_check.instance_eval{guid_pairs.any?{|e| self | e == self and e | self == e}} # => true 
    array_to_check.instance_eval{guid_pairs.any?{|e| self & e == self and e & self == e}} # => true 
+0

Je voudrais éviter tableau de correction de singe juste pour un cas d'utilisation. –

+0

@Joshua J'ai modifié ma réponse. – sawa

4

Pour voir si deux tableaux contiennent les mêmes éléments, indépendamment de l'ordre, vous pouvez utiliser l'opération XOR (exclusive ou). Il retournera un tableau qui contient seulement les éléments qui sont dans un tableau et pas l'autre. Si la longueur du XOR est nulle alors les tableaux d'entrée contiennent les mêmes éléments.

def xor(a, b) 
    (a | b) - (a & b) 
end 

guid_pairs.any? { |pair| xor(pair, array_to_check).length != 0 } 
1

pour l'égalité des deux tableaux A et B i utilisent normalement:

if(((A-B) + (B-A)).blank?) 
    puts "equal" 
else 
    "unequal" 
end