Donné:
a1 = [5, 1, 6, 14, 2, 8]
Je voudrais déterminer s'il contient tous les éléments de:
a2 = [2, 6, 15]
Dans ce cas, le résultat est false
.
Existe-t-il des méthodes Ruby / Rails intégrées pour identifier une telle inclusion de tableau?
Une façon de mettre en œuvre ceci est:
a2.index{ |x| !a1.include?(x) }.nil?
Existe-t-il une meilleure façon, plus lisible?
ruby-on-rails
arrays
ruby
Misha Moroshko
la source
la source
Réponses:
a = [5, 1, 6, 14, 2, 8] b = [2, 6, 15] a - b # => [5, 1, 14, 8] b - a # => [15] (b - a).empty? # => false
la source
(a2-a1).empty?
(a2.uniq - a1.uniq).empty?
C'est peut-être plus facile à lire:
a2.all? { |e| a1.include?(e) }
Vous pouvez également utiliser l'intersection de tableau:
Notez que
size
c'est utilisé ici uniquement pour la vitesse, vous pouvez également faire (plus lentement):Mais je suppose que le premier est plus lisible. Ces 3 sont du rubis uni (pas des rails).
la source
Ceci peut être réalisé en faisant
Cela crée l'intersection des deux tableaux, renvoyant tous les éléments à partir
a2
desquels se trouvent égalementa1
. Si le résultat est le même quea2
, vous pouvez être sûr que tous les éléments sont inclus dansa1
.Cette approche ne fonctionne que si tous les éléments de
a2
sont différents les uns des autres en premier lieu. S'il y a des doubles, cette approche échoue. Celui de Tempos fonctionne toujours alors, je recommande donc de tout cœur son approche (aussi c'est probablement plus rapide).la source
length
méthode fonctionnera beaucoup mieuxS'il n'y a pas d'éléments en double ou que vous ne vous souciez pas d'eux, vous pouvez utiliser la classe Set :
a1 = Set.new [5, 1, 6, 14, 2, 8] a2 = Set.new [2, 6, 15] a1.subset?(a2) => false
Dans les coulisses, cela utilise
all? { |o| set.include?(o) }
la source
Vous pouvez monkey-patcher la classe Array:
class Array def contains_all?(ary) ary.uniq.all? { |x| count(x) >= ary.count(x) } end end
tester
irb(main):131:0> %w[a b c c].contains_all? %w[a b c] => true irb(main):132:0> %w[a b c c].contains_all? %w[a b c c] => true irb(main):133:0> %w[a b c c].contains_all? %w[a b c c c] => false irb(main):134:0> %w[a b c c].contains_all? %w[a] => true irb(main):135:0> %w[a b c c].contains_all? %w[x] => false irb(main):136:0> %w[a b c c].contains_all? %w[] => true irb(main):137:0> %w[a b c d].contains_all? %w[d c h] => false irb(main):138:0> %w[a b c d].contains_all? %w[d b c] => true
Bien sûr, la méthode peut être écrite comme une méthode standard, par exemple
def contains_all?(a,b) b.uniq.all? { |x| a.count(x) >= b.count(x) } end
et vous pouvez l'invoquer comme
contains_all?(%w[a b c c], %w[c c c])
En effet, après profilage, la version suivante est beaucoup plus rapide, et le code est plus court.
def contains_all?(a,b) b.all? { |x| a.count(x) >= b.count(x) } end
la source
En fonction de la taille de vos tableaux, vous pouvez envisager un algorithme efficace O (n log n)
def equal_a(a1, a2) a1sorted = a1.sort a2sorted = a2.sort return false if a1.length != a2.length 0.upto(a1.length - 1) do |i| return false if a1sorted[i] != a2sorted[i] end end
Le tri coûte O (n log n) et la vérification de chaque paire coûte O (n) donc cet algorithme est O (n log n). Les autres algorithmes ne peuvent pas être plus rapides (asymptotiquement) en utilisant des tableaux non triés.
la source
La plupart des réponses basées sur (a1 - a2) ou (a1 & a2) ne fonctionneraient pas s'il y a des éléments en double dans l'un ou l'autre des tableaux. Je suis arrivé ici à la recherche d'un moyen de voir si toutes les lettres d'un mot (divisé en un tableau) faisaient partie d'un ensemble de lettres (pour le scrabble par exemple). Aucune de ces réponses n'a fonctionné, mais celle-ci fonctionne:
def contains_all?(a1, a2) try = a1.chars.all? do |letter| a1.count(letter) <= a2.count(letter) end return try end
la source