Je dois vérifier si deux tableaux contiennent les mêmes données dans n'importe quel ordre. En utilisant la méthode imaginaire compare
, je voudrais faire:
arr1 = [1,2,3,5,4]
arr2 = [3,4,2,1,5]
arr3 = [3,4,2,1,5,5]
arr1.compare(arr2) #true
arr1.compare(arr3) #false
J'ai utilisé arr1.sort == arr2.sort
, ce qui semble fonctionner, mais existe-t-il une meilleure façon de procéder?
Le tri des tableaux avant de les comparer est O (n log n). De plus, comme le souligne Victor, vous rencontrerez des problèmes si le tableau contient des objets non triables. Il est plus rapide de comparer les histogrammes, O (n).
Vous trouverez Enumerable # fréquence dans Facets, mais implémentez-le vous-même, ce qui est assez simple, si vous préférez éviter d'ajouter plus de dépendances:
require 'facets'
[1, 2, 1].frequency == [2, 1, 1].frequency
#=> true
Le moyen le plus simple consiste à utiliser les intersections:
@array1 = [1,2,3,4,5]
@array2 = [2,3,4,5,1]
Donc, la déclaration
@array2 & @array1 == @array2
Sera true
. C'est la meilleure solution si vous souhaitez vérifier si array1
contient array2
ou l'inverse (c'est différent). Vous ne jouez pas non plus avec vos tableaux ni ne changez l'ordre des articles. Vous pouvez également comparer la longueur des deux tableaux si vous souhaitez qu'ils soient de taille identique.
C'est aussi le moyen le plus rapide de le faire (corrigez-moi si je me trompe)
Si vous savez qu'il n'y a pas de répétitions dans aucun des tableaux (c'est-à-dire que tous les éléments sont uniques ou que vous ne vous souciez pas), l'utilisation d'ensembles est simple et lisible:
Set.new(array1) == Set.new(array2)
Vous pouvez réellement implémenter ce #compare
méthode par patch de singe la classe Array comme ceci:
class Array
def compare(other)
sort == other.sort
end
end
Gardez à l'esprit que le patch de singe est rarement considéré comme une bonne pratique et vous devez être prudent lorsque vous l'utilisez.
Il existe probablement une meilleure façon de procéder, mais c'est ce qui m'est venu à l'esprit. J'espère que ça aide!
Vous pouvez ouvrir la classe array
et définir une méthode comme celle-ci.
class Array
def compare(comparate)
to_set == comparate.to_set
end
end
arr1.compare(arr2)
irb => true
OU utilisez simplement
arr1.to_set == arr2.to_set
irb => true
La manière la plus élégante que j'ai trouvée:
arr1 = [1,2,3,5,4]
arr2 = [3,4,2,1,5]
arr3 = [3,4,2,1,5,5]
(arr1 - arr2).empty?
=> true
(arr3 - arr2).empty?
=> false
Voici une version qui fonctionnera sur des tableaux non triables
class Array
def unordered_hash
unless @_compare_o && @_compare_o == hash
p = Hash.new(0)
each{ |v| p[v] += 1 }
@_compare_p = p.hash
@_compare_o = hash
end
@_compare_p
end
def compare(b)
unordered_hash == b.unordered_hash
end
end
a = [ 1, 2, 3, 2, nil ]
b = [ nil, 2, 1, 3, 2 ]
puts a.compare(b)