Cómo determinar si un array contiene todos los elementos de otro array
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 matrices?
Una forma de implementar esto es:
a2.index{ |x| !a1.include?(x) }.nil?
¿Hay una manera mejor, más legible?
6 answers
a = [5, 1, 6, 14, 2, 8]
b = [2, 6, 15]
a - b
=> [5, 1, 14, 8]
b - a
=> [15]
(b - a).empty?
=> false
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-25 16:13:36
Tal vez esto sea más fácil de leer:
a2.all? { |e| a1.include?(e) }
También puede usar la intersección de matrices:
(a1 & a2).size == a1.size
Tenga en cuenta que size
se utiliza aquí solo para la velocidad, también puede hacer (más lento):
(a1 & a2) == a1
Pero supongo que el primero es más legible. Estos 3 son rubíes simples (no rieles).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-12 12:42:39
Esto se puede lograr haciendo
(a2 & a1) == a2
Esto crea la intersección de ambos arrays, 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, así que recomiendo de todo corazón su enfoque (también es probablemente más rápido).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-01 22:05:26
Si no hay elementos duplicados o no te importan, entonces 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 que utiliza
all? { |o| set.include?(o) }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-12 17:22:35
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
Ordenar los costos O(n log n) y verificar 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) usando arrays sin clasificar.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-12 17:36:19
Usted puede monkey-parchear 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[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
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[a b c c], %w[c c c])
De hecho, después de perfilar, 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-15 16:28:45