2009-07-28 38 views
68

Tengo dos matrices de tareas: creadas y asignadas. Quiero eliminar todas las tareas asignadas de la matriz de tareas creadas. Aquí es mi trabajo, pero desordenado, código:Restar una matriz de otra en Ruby

@assigned_tasks = @user.assigned_tasks 
    @created_tasks = @user.created_tasks 

    #Do not show created tasks assigned to self 
    @created_not_doing_tasks = Array.new 
    @created_tasks.each do |task| 
     unless @assigned_tasks.include?(task) 
      @created_not_doing_tasks << task 
     end 
    end 

Estoy seguro de que hay una mejor manera. ¿Qué es? Gracias :-)

+0

Apuesto a que la respuesta es hacer exactamente lo que has codificado allí. – baash05

Respuesta

147

Puede restar matrices en Ruby:

[1,2,3,4,5] - [1,3,4] #=> [2,5] 

ary - other_ary → Diferencia de matriz new_ary

Devuelve una nueva matriz que es una copia de la matriz original, la eliminación cualquier elementos que también aparecen en other_ary. El orden se preserva de la matriz original .

se compara elementos que utilizan su hash y eql? métodos para la eficiencia.

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]

Si necesita comportamiento conjunto similar, consulte el conjunto de la clase biblioteca.

Consulte la documentación de Array.

+2

Arg. Gran momento cara-palma para mí. Por alguna razón, pensé que eso no funcionaría con los objetos. Funcionó bien, ¡gracias! – doctororange

+1

np, sucede :) – hobodave

+25

cuidado con esto, un ensayo en la primera IRB, por ejemplo: [5, 5, 5, 5] - [5, 5] = [] ... la sustracción elimina los elementos singulares de la formación. – hagope

4

La solución anterior

a - b 

elimina todas las instancias de elementos de array b de array a.

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ] 

En algunos casos, usted quiere que el resultado sea [1, 2, 3, 3, 5]. Es decir, no desea eliminar todos los duplicados, sino solo los elementos individualmente.

Se podría lograr esto mediante

class Array 
    def delete_elements_in(ary) 
    ary.each do |x| 
     if index = index(x) 
     delete_at(index) 
     end 
    end 
end 

prueba

irb(main):198:0> a = [ 1, 1, 2, 2, 3, 3, 4, 5 ] 
=> [1, 1, 2, 2, 3, 3, 4, 5] 
irb(main):199:0> b = [ 1, 2, 4 ] 
=> [1, 2, 4] 
irb(main):200:0> a.delete_elements_in(b) 
=> [1, 2, 4] 
irb(main):201:0> a 
=> [1, 2, 3, 3, 5] 

El código funciona incluso cuando las dos matrices no están ordenados. En el ejemplo, las matrices están ordenadas, pero esto no es obligatorio.

Cuestiones relacionadas