2012-01-19 13 views
51

Diciamo che sto cercando di rimuovere elementi dall'array a = [1,1,1,2,2,3]. Se eseguo il seguente:Rimozione elementi dall'array Ruby

b = a - [1,3] 

Poi mi metterò:

b = [2,2] 

Tuttavia, voglio che il risultato sia

b = [1,1,2,2] 

cioè rimuovo una sola istanza di ogni elemento il vettore sottratto non tutti i casi. C'è un modo semplice in Ruby per fare questo?

+0

Se si sottrae '[1,1,3]' cosa desiderate finire con 'b = [1,2,2]'? O non succederà mai? – seph

risposta

63

Si può fare:

a= [1,1,1,2,2,3] 
delete_list = [1,3] 
delete_list.each do |del| 
    a.delete_at(a.index(del)) 
end 

risultato: [1, 1, 2, 2]

+1

Quindi la sottrazione dell'array è in realtà disgiunta-Set? –

+1

Differenza array --- Restituisce un nuovo array che è una copia dell'array originale, rimuovendo tutti gli elementi che appaiono anche in other_ary. (Se è necessario il comportamento set-like, vedere la classe di libreria Set.) [Link] (http://www.ruby-doc.org/core-1.9.3/Array.html) – Norm212

+2

Se si desidera rimuovere tutte le istanze di elementi in 'delete_list', puoi farlo. 'b = a.each.reject {| x | delete_list.each.include? x} ' – Archonic

2

Non molto semplice ma:

a = [1,1,1,2,2,3] 
b = a.group_by {|n| n}.each {|k,v| v.pop [1,3].count(k)}.values.flatten 
=> [1, 1, 2, 2] 

gestisce anche il caso per i multipli del 'subtrahend':

a = [1,1,1,2,2,3] 
b = a.group_by {|n| n}.each {|k,v| v.pop [1,1,3].count(k)}.values.flatten 
=> [1, 2, 2] 

MODIFICA: questo è mor e un miglioramento che unisce Norm212 e la mia risposta per creare una soluzione "funzionale".

b = [1,1,3].each.with_object(a) { |del| a.delete_at(a.index(del)) } 

Mettetela in un lambda, se necessario:

subtract = lambda do |minuend, subtrahend| 
    subtrahend.each.with_object(minuend) { |del| minuend.delete_at(minuend.index(del)) } 
end 

poi:

subtract.call a, [1,1,3] 
+0

No, l'ordine potrebbe essere modificato. Sembra che Norm212 mantenga l'ordine. – seph

+0

@ Michael, per favore guarda le modifiche – seph

3
[1,3].inject([1,1,1,2,2,3]) do |memo,element| 
    memo.tap do |memo| 
    i = memo.find_index(e) 
    memo.delete_at(i) if i 
    end 
end 
Problemi correlati