Cómo determinar si una matriz contiene todos los elementos de otra matriz

Dado:

a1 = [5, 1, 6, 14, 2, 8] 

Me gustaría determinar si contiene todos los elementos de:

 a2 = [2, 6, 15] 

En este caso, el resultado es false .

¿Hay algún método incorporado de Ruby / Rails para identificar dicha inclusión de matriz?

Una forma de implementar esto es:

 a2.index{ |x| !a1.include?(x) }.nil? 

¿Hay una forma mejor y más legible?

 a = [5, 1, 6, 14, 2, 8] b = [2, 6, 15] a - b => [5, 1, 14, 8] b - a => [15] (b - a).empty? => false 

Tal vez esto es más fácil de leer:

 a2.all? { |e| a1.include?(e) } 

También puede usar la intersección de matriz:

 (a1 & a2).size == a1.size 

Tenga en cuenta que el size se usa aquí solo para la velocidad, también puede hacerlo (más lento):

 (a1 & a2) == a1 

Pero creo que el primero es más legible. Estos 3 son Ruby simple (no Rails).

Esto se puede lograr haciendo

 (a2 & a1) == a2 

Esto crea la intersección de ambas matrices, devolviendo todos los elementos de a2 que también están en a1 . Si el resultado es el mismo que a2 , puede estar seguro de que tiene todos los elementos incluidos en a1 .

Este enfoque solo funciona si todos los elementos en a2 son diferentes entre sí en primer lugar. Si hay dobles, este enfoque falla. El de Tempos todavía funciona entonces, por lo que recomiendo sinceramente su enfoque (también es probable que sea más rápido).

Si no hay elementos duplicados o si no te importan, puedes usar la clase Set :

 a1 = Set.new [5, 1, 6, 14, 2, 8] a2 = Set.new [2, 6, 15] a1.subset?(a2) => false 

Detrás de las escenas esto usa

 all? { |o| set.include?(o) } 

Dependiendo de cuán grandes sean sus matrices, podría considerar un algoritmo eficiente 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 

La ordenación cuesta O (n log n) y la comprobación de cada par cuesta O (n), por lo que este algoritmo es O (n log n). Los otros algoritmos no pueden ser más rápidos (asintóticamente) utilizando matrices no ordenadas.

Puedes aplicar un parche de mono a la clase Array:

 class Array def contains_all?(ary) ary.uniq.all? { |x| count(x) >= ary.count(x) } end end 

prueba

 irb(main):131:0> %w[abcc].contains_all? %w[abc] => true irb(main):132:0> %w[abcc].contains_all? %w[abcc] => true irb(main):133:0> %w[abcc].contains_all? %w[abccc] => false irb(main):134:0> %w[abcc].contains_all? %w[a] => true irb(main):135:0> %w[abcc].contains_all? %w[x] => false irb(main):136:0> %w[abcc].contains_all? %w[] => true irb(main):137:0> %w[abcd].contains_all? %w[dch] => false irb(main):138:0> %w[abcd].contains_all? %w[dbc] => true 

Por supuesto, el método se puede escribir como un método estándar solo, por ejemplo

 def contains_all?(a,b) b.uniq.all? { |x| a.count(x) >= b.count(x) } end 

y puedes invocarlo como

 contains_all?(%w[abcc], %w[ccc]) 

De hecho, después del perfilado, la siguiente versión es mucho más rápida y el código es más corto.

 def contains_all?(a,b) b.all? { |x| a.count(x) >= b.count(x) } end