Come posso eliminare un elemento da un array in base al valore


343

Ho una serie di elementi in Ruby

[2,4,6,3,8]

Ho bisogno di rimuovere elementi con valore 3per esempio

Come lo faccio?


mi chiedo perché delete array.delete(3)non
— funzioni con

2
potrebbe essere dovuto al active recordmetododelete
— ImranNaqvi,

Risposte:


481

Penso di averlo capito:

a = [3, 2, 4, 6, 3, 8]
a.delete(3)
#=> 3
a
#=> [2, 4, 6, 8]

189
Personalmente, come [1, 2, 3, 4, 5] - [3]che si traduce in => [1, 2, 4, 5]da irb.
— Travis,

24
E se ci fossero più voci di 3 e volessimo eliminarne solo una? (Questo è collegato, quindi chiedere questo qui potrebbe essere il migliore)
— Navneet,

113
Solo un avvertimento che .delete () restituirà il valore eliminato, non l'array modificato con il valore rimosso.
— Joshua Pinter,

23
L'altra conseguenza da considerare è che deletemuta l'array sottostante mentre -crea un nuovo array (che ti viene restituito) senza il valore eliminato. A seconda del caso d'uso, entrambi gli approcci possono avere senso.
— srt32,

2
@ user3721428, delete (3) non si riferisce all'elemento in posizione 3 ma elimina invece qualsiasi elemento corrispondente all'intero 3. Rimuoverà tutte le occorrenze di 3 e non ha nulla a che fare con l'indice o la posizione delle matrici.
— bkunzi01,

226

Prendendo in prestito Travis nei commenti, questa è una risposta migliore:

Personalmente, come [1, 2, 7, 4, 5] - [7]che si traduce in => [1, 2, 4, 5]dairb

Ho modificato la sua risposta vedendo che 3 era il terzo elemento nella sua matrice di esempio. Ciò potrebbe creare confusione per coloro che non si rendono conto che 3 è nella posizione 2 dell'array.


21
Come sottolinea srt32 nella risposta, c'è una distinzione importante da fare tra l'utilizzo di .deletee -. .deleterestituirà il valore che è stato rimosso dall'array, se presente; -no. Quindi [ 1, 2, 3 ] - [ 2 ]tornerà [ 1, 3 ], mentre [ 1, 2, 3 ].delete( 2 )tornerà 2.
— Argus9,

5
array - subArraynon funzionerà per Array of Arrays , ma array.delete(subArray)funzionerà.
— Sachin,

21
La differenza molto importante tra [1,2,3] - [2]e [1,2,3].delete(2)è che il deletemetodo modifica l'array originale , mentre [1,2,3] - [3]crea un nuovo array .
— Timothy Kovalev,

Re subarrays (commento di @Sachin sopra) "Certo che lo farà", devi solo prendere la notazione giusta: [1,2,[2],2,3,4] - [2]ti dà [1, [2], 3, 4], ma [1,2,[2],2,3,4] - [[2]]ti dà [1, 2, 2, 3, 4]. :-)
— Tom Hundt,

69

Un'altra opzione:

a = [2,4,6,3,8]

a -= [3]

che risulta in

=> [2, 4, 6, 8] 

50

Non sono sicuro che qualcuno l'abbia dichiarato, ma Array.delete () e - = value elimineranno ogni istanza del valore passato all'interno dell'array. Al fine di eliminare la prima istanza dell'elemento particolare è possibile fare qualcosa di simile

arr = [1,3,2,44,5]
arr.delete_at(arr.index(44))

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

Potrebbe esserci un modo più semplice. Non sto dicendo che questa è la migliore pratica, ma è qualcosa che dovrebbe essere riconosciuto.


1
Stavo cercando un modo per farlo ed eliminare solo un'istanza dell'elemento in caso di duplicati e questo funziona alla grande!
— xeroshogun,

Penso che questa risposta sia sbagliata, semplicemente perché arr.index () potrebbe andarenil
— windmaomao,

32

Supponendo che si desideri eliminare 3 in base al valore in più punti di un array, penso che il modo ruby ​​per eseguire questa attività sarebbe utilizzare il metodo delete_if:

[2,4,6,3,8,3].delete_if {|x| x == 3 } 

Puoi anche usare delete_if per rimuovere elementi nello scenario di "array di matrici".

Spero che questo risolva la tua domanda


25

mi piace il -=[4] modo menzionato in altre risposte per eliminare gli elementi il ​​cui valore è 4.

Ma c'è così:

irb(main):419:0> [2,4,6,3,8,6].delete_if{|i|i==6}
=> [2, 4, 3, 8]
irb(main):420:0>

menzionato da qualche parte in " Operazioni di base sull'array ", dopo che menziona la mapfunzione.


Ma non puoi semplicemente usare.delete(6)
— Zac

@Zac, naturalmente, ma la risposta è già stato menzionato (così come il molto conciso -=modo a-=[4] cioè a=a-[4]. [3,4]-[4], Che ho detto mi è piaciuto), ma ho voluto citare un altro modo possibile.
— barlop

Questo metodo ha anche il vantaggio di restituire l'array anziché l'elemento eliminato.
— F.Webber,



15

Ecco alcuni parametri di riferimento:

require 'fruity'


class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8]

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test 4096 times. Test will take about 2 seconds.
# >> soziev is similar to barlop
# >> barlop is faster than steve by 2x ± 1.0
# >> steve is faster than rodrigo by 4x ± 1.0
# >> rodrigo is similar to niels

E ancora con un array più grande che contiene molti duplicati:

class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8] * 1000

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test 16 times. Test will take about 1 second.
# >> steve is faster than soziev by 30.000000000000004% ± 10.0%
# >> soziev is faster than barlop by 50.0% ± 10.0%
# >> barlop is faster than rodrigo by 3x ± 0.1
# >> rodrigo is similar to niels

E ancora più grande con più duplicati:

class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8] * 100_000

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test once. Test will take about 6 seconds.
# >> steve is similar to soziev
# >> soziev is faster than barlop by 2x ± 0.1
# >> barlop is faster than niels by 3x ± 1.0
# >> niels is similar to rodrigo

7
Allora, qual è il migliore? :)
— Kirby,

8

Ho migliorato la soluzione di Niels

class Array          
  def except(*values)
    self - values
  end    
end

Ora puoi usare

[1, 2, 3, 4].except(3, 4) # return [1, 2]
[1, 2, 3, 4].except(4)    # return [1, 2, 3]

La tua soluzione non funziona su irbconsole 2.2.1 :007 > [1, 2, 3, 4].except(3, 4) NoMethodError: undefined method except for [1, 2, 3, 4]:Array from (irb):7 from /usr/share/rvm/rubies/ruby-2.2.1/bin/irb:11:in <main>
— hgsongra,

1
Per dichiarare in IRB, è necessario aggiungere il metodo all'array class Array; def except(*values); self - values; end; end.
— Mark Swardstrom

3

Puoi anche scimmia patch. Non ho mai capito perché Ruby abbia un exceptmetodo per Hashma non per Array:

class Array
  def except value
    value = value.kind_of(Array) ? value : [value]
    self - value
  end
end

Ora puoi fare:

[1,3,7,"436",354,nil].except(354) #=> [1,3,7,"436",nil]

O:

[1,3,7,"436",354,nil].except([354, 1]) #=> [3,7,"436",nil]

1
Non hai bisogno del value.kind_of(Array)test. Basta usare self - Array(value).
— Sasgorilla,

3

Quindi quando hai più occorrenze di 3 e vuoi solo eliminare la prima occorrenza di 3, puoi semplicemente fare qualcosa come di seguito.

arr = [2, 4, 6, 3, 8, 10, 3, 12]

arr.delete_at arr.index 3

#This will modify arr as [2, 4, 6, 8, 10, 3, 12] where first occurrence of 3 is deleted. Returns the element deleted. In this case => 3.

3

Rimozione non distruttiva della prima occorrenza:

a = [2, 4, 6, 3, 8]
n = a.index 3
a.take(n)+a.drop(n+1)

2

Se si desidera anche rendere questa operazione di eliminazione concatenabile, in modo da poter eliminare alcuni elementi e continuare a concatenare le operazioni sull'array risultante, utilizzare tap:

[2, 4, 6, 3, 8].tap { |ary| ary.delete(3) }.count #=> 4

1

Compilando tutte le diverse opzioni per l'eliminazione in ruby

elimina : elimina gli elementi corrispondenti in base al valore. Se più di un valore corrisponde rimuoverà tutto. Se non ti interessa il numero di occorrenze o sei sicuro di una singola occorrenza, utilizza questo metodo.

a = [2, 6, 3, 5, 3, 7]
a.delete(3)  # returns 3
puts a       # return [2, 6, 5, 7]

delete_at - Elimina l'elemento in un determinato indice. Se conosci l'indice usa questo metodo.

# continuing from the above example
a.delete_at(2) # returns 5
puts a         # returns [2, 6, 7]

delete_if - Elimina tutti gli elementi per i quali il blocco è vero. Questo modificherà l'array. La matrice cambia istantaneamente quando viene chiamato il blocco.

b = [1, 2, 5, 4, 9, 10, 11]
b.delete_if {|n| n >= 10}.  # returns [1, 2, 5, 4, 9]

Rifiuta : questo restituirà un nuovo array con gli elementi per i quali il blocco dato è falso. L'ordinamento è mantenuto con questo.

c = [1, 2, 5, 4, 9, 10, 11]
c.reject {|n| n >= 10}.  # returns [1, 2, 5, 4, 9]

rifiutare! - uguale a delete_if . L'array potrebbe non cambiare istantaneamente quando viene chiamato il blocco.

Se si desidera eliminare più valori dall'array, l'opzione migliore è la seguente.

a = [2, 3, 7, 4, 6, 21, 13]
b = [7, 21]
a = a - b    # a - [2, 3, 4, 6, 13]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.