Wie kann ich ein Element nach Wert aus einem Array löschen?


343

Ich habe eine Reihe von Elementen in Ruby

[2,4,6,3,8]

Ich muss zum 3Beispiel Elemente mit Wert entfernen

Wie mache ich das?


Ich frage mich, warum delete array.delete(3)nicht innerhalb von Ruby on Rails Controller
funktioniert

2
kann auf active recordMethode zurückzuführen seindelete
ImranNaqvi

Antworten:


481

Ich glaube, ich habe es herausgefunden:

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

189
Ich persönlich mag [1, 2, 3, 4, 5] - [3]die Ergebnisse in => [1, 2, 4, 5]aus irb.
Travis

24
Was ist, wenn es mehrere Einträge von 3 gibt und wir nur einen von ihnen löschen wollten? (Dies ist verwandt, so dass es am besten ist, dies hier zu fragen)
Navneet

113
Nur ein Hinweis darauf, dass .delete () den gelöschten Wert zurückgibt, nicht das geänderte Array, bei dem der Wert entfernt wurde.
Joshua Pinter

23
Die andere zu berücksichtigende Konsequenz ist, dass deletedas zugrunde liegende Array mutiert wird, während -ein neues Array (das an Sie zurückgegeben wird) ohne den gelöschten Wert erstellt wird. Abhängig von Ihrem Anwendungsfall kann jeder Ansatz sinnvoll sein.
srt32

2
@ user3721428, delete (3) bezieht sich nicht auf das Element in Position 3, sondern löscht stattdessen alle Elemente, die mit der Ganzzahl 3 übereinstimmen. Es entfernt alle Vorkommen von 3 und hat nichts mit dem Index oder der Position des Arrays zu tun.
bkunzi01

226

In Anlehnung an Travis in den Kommentaren ist dies eine bessere Antwort:

Ich persönlich mag , [1, 2, 7, 4, 5] - [7]welche Ergebnisse in => [1, 2, 4, 5]vonirb

Ich habe seine Antwort dahingehend geändert, dass 3 das dritte Element in seinem Beispielarray ist. Dies könnte zu Verwirrung bei denjenigen führen, die nicht erkennen, dass sich 3 im Array auf Position 2 befindet.


21
Wie srt32 in der Antwort hervorhebt, gibt es einen wichtigen Unterschied zwischen der Verwendung von .deleteund -. .deletegibt den Wert zurück, der aus dem Array entfernt wurde, falls vorhanden; -wird nicht. Also [ 1, 2, 3 ] - [ 2 ]wird zurückkehren [ 1, 3 ], während [ 1, 2, 3 ].delete( 2 )wird zurückkehren 2.
Argus9

5
array - subArrayfunktioniert nicht für Array of Arrays , reicht aber aus array.delete(subArray).
Sachin

20
Der sehr wichtige Unterschied zwischen [1,2,3] - [2]und [1,2,3].delete(2)besteht darin, dass die deleteMethode das ursprüngliche Array ändert und gleichzeitig [1,2,3] - [3]ein neues Array erstellt .
Timothy Kovalev

Re Subarrays (@ Sachins Kommentar oben) "Sicher wird es", müssen Sie nur die Notation richtig machen: [1,2,[2],2,3,4] - [2]gibt Ihnen [1, [2], 3, 4], aber [1,2,[2],2,3,4] - [[2]]gibt Ihnen [1, 2, 2, 3, 4]. :-)
Tom Hundt

69

Andere Option:

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

a -= [3]

was in ... resultiert

=> [2, 4, 6, 8] 

50

Ich bin nicht sicher, ob jemand dies angegeben hat, aber Array.delete () und - = value löschen jede Instanz des Wertes, der innerhalb des Arrays an ihn übergeben wurde. Um die erste Instanz des jeweiligen Elements zu löschen, können Sie so etwas tun

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

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

Es könnte einen einfacheren Weg geben. Ich sage nicht, dass dies eine bewährte Methode ist, aber es ist etwas, das anerkannt werden sollte.


1
Ich habe nach einer Möglichkeit gesucht, dies zu tun und nur eine Instanz des Elements zu löschen, falls Duplikate vorhanden sind, und dies funktioniert hervorragend!
Xeroshogun

Ich denke, diese Antwort ist falsch, einfach weil arr.index () gehen könntenil
windmaomao

32

Angenommen, Sie möchten 3 nach Wert an mehreren Stellen in einem Array löschen. Ich denke, die rubinrote Methode für diese Aufgabe wäre die Verwendung der Methode delete_if:

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

Sie können delete_if auch zum Entfernen von Elementen im Szenario 'Array of Arrays' verwenden.

Hoffe, dies löst Ihre Anfrage


25

Ich mag die -=[4]in anderen Antworten erwähnte Methode, um die Elemente zu löschen, deren Wert 4 ist.

Aber es gibt diesen Weg:

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

irgendwo in " Basic Array Operations " erwähnt, nachdem die mapFunktion erwähnt wurde.


Aber können Sie nicht einfach verwenden.delete(6)
Zac

@Zac natürlich , aber diese Antwort bereits erwähnt wurde (ebenso wie die sehr prägnante -=Art und Weise , a-=[4]dh a=a-[4]. [3,4]-[4], Die ich sagte , ich möchte), aber ich wollte eine andere Art und Weise , ganz zu schweigen.
Barlop

Diese Methode hat auch den Vorteil, dass das Array anstelle des gelöschten Elements zurückgegeben wird.
F. Webber



15

Hier einige Benchmarks:

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

Und wieder mit einem größeren Array, das viele Duplikate enthält:

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

Und noch größer mit mehr Duplikaten:

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
Also, was ist das Beste davon? :)
Kirby

8

Ich habe Niels 'Lösung verbessert

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

Jetzt können Sie verwenden

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

Ihre Lösung funktioniert nicht auf der irbKonsole 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
Um in IRB zu deklarieren, müssen Sie die Methode zu Array hinzufügen class Array; def except(*values); self - values; end; end.
Mark Swardstrom

3

Sie können es auch mit Affen patchen. Ich habe nie verstanden, warum Ruby eine exceptMethode hat, Hashaber nicht für Array:

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

Jetzt können Sie Folgendes tun:

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

Oder:

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

1
Du brauchst den value.kind_of(Array)Test nicht. Einfach benutzen self - Array(value).
Sasgorilla

3

Wenn Sie also mehrere Vorkommen von 3 haben und nur das erste Vorkommen von 3 löschen möchten, können Sie einfach Folgendes tun.

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

Zerstörungsfreie Beseitigung des ersten Auftretens:

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

2

Wenn Sie diesen Löschvorgang auch verkettbar machen möchten, damit Sie einige Elemente löschen und die Verkettungsvorgänge für das resultierende Array fortsetzen können, verwenden Sie tap:

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

1

Kompilieren aller verschiedenen Optionen zum Löschen in Ruby

Löschen - Löscht übereinstimmende Elemente nach Wert. Wenn mehr als ein Wert übereinstimmt, werden alle entfernt. Verwenden Sie diese Methode, wenn Sie sich nicht für die Anzahl der Vorkommen interessieren oder sich nicht sicher sind, ob sie einmal auftreten.

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

delete_at - Löscht das Element am angegebenen Index. Wenn Sie den Index kennen, verwenden Sie diese Methode.

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

delete_if - Löscht jedes Element, für das ein Block wahr ist. Dadurch wird das Array geändert. Das Array ändert sich sofort, wenn der Block aufgerufen wird.

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

ablehnen - Dies gibt ein neues Array mit den Elementen zurück, für die der angegebene Block falsch ist. Die Bestellung bleibt dabei erhalten.

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

ablehnen! - wie delete_if . Das Array ändert sich möglicherweise nicht sofort, wenn der Block aufgerufen wird.

Wenn Sie mehrere Werte aus dem Array löschen möchten, ist die beste Option wie folgt.

a = [2, 3, 7, 4, 6, 21, 13]
b = [7, 21]
a = a - b    # a - [2, 3, 4, 6, 13]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.