2009-07-28 11 views
68

Ho due matrici di attività, create e assegnate. Voglio rimuovere tutte le attività assegnate dalla serie di attività create. Ecco il mio lavoro, ma disordinato, di codice:Sottrarre una matrice da un'altra in 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 

Sono sicuro che c'è un modo migliore. Che cos'è? Grazie :-)

+0

Scommetto che la risposta sta facendo proprio quello che hai codificato lì. – baash05

risposta

147

È possibile sottrarre array in Ruby:

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

ary - other_ary → Differenza Array new_ary

restituisce un nuovo array che è una copia della matrice originale, rimuovendo qualsiasi elemento visualizzato anche in other_ary. L'ordine viene preservato dall'array originale .

Confronta gli elementi utilizzando il loro hash ed eql? metodi per l'efficienza.

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

Se avete bisogno di set-simile comportamento, vedere la Set Libreria di classi.

Vedere la documentazione Array.

+2

Arg. Momento di grande faccia da palmo per me. Per qualche ragione ho pensato che non avrebbe funzionato con gli oggetti. Ha funzionato bene, grazie! – doctororange

+1

np, succede :) – hobodave

+25

attento a questo, testarlo prima in IRB, ad esempio: [5, 5, 5, 5] - [5, 5] = [] ... la sottrazione rimuove gli elementi univoci nel array. – hagope

4

La soluzione sopra

a - b 

elimina tutte le istanze di elementi dell'array b dalla matrice a.

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

In alcuni casi, si desidera che il risultato sia [1, 2, 3, 3, 5]. Cioè, non si desidera eliminare tutti i duplicati, ma solo gli elementi individualmente.

Si potrebbe raggiungere questo obiettivo

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

prova

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] 

Il codice funziona anche quando i due array non sono ordinati. Nell'esempio, gli array sono ordinati, ma questo non è richiesto.

Problemi correlati