webentwicklung-frage-antwort-db.com.de

Elemente aus dem Array Ruby entfernen

Angenommen, ich versuche, Elemente aus dem Array a = [1,1,1,2,2,3] zu entfernen. Wenn ich Folgendes durchführe:

b = a - [1,3]

Dann werde ich bekommen:

b = [2,2]

Ich möchte jedoch das Ergebnis

b = [1,1,2,2]

ich entferne nur eine Instanz jedes Elements in dem subtrahierten Vektor, nicht in allen Fällen. Gibt es in Ruby einen einfachen Weg, dies zu tun?

58
Michael

Sie können tun:

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

ergebnis: [1, 1, 2, 2]

69
Norm212
[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
5
zetetic

Nicht ganz einfach, aber:

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]

Behandelt auch den Fall für Vielfache im '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]

BEARBEITEN: Dies ist eher eine Verbesserung, die Norm212 und meine Antwort zu einer "funktionalen" Lösung kombiniert.

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

Wenn nötig in ein Lambda legen:

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

dann:

subtract.call a, [1,1,3]
3
seph

Für die Geschwindigkeit würde ich Folgendes tun, was nur einen Durchlauf durch jedes der beiden Arrays erfordert. Diese Methode bewahrt die Ordnung. Ich werde zunächst Code präsentieren, der das ursprüngliche Array nicht mutiert, und dann zeigen, wie er leicht verändert werden kann.

arr = [1,1,1,2,2,3,1]
removals = [1,3,1]

h = removals.group_by(&:itself).transform_values(&:size)
  #=> {1=>2, 3=>1} 
arr.each_with_object([]) { |n,a|
  h.key?(n) && h[n] > 0 ? (h[n] -= 1) : a << n }
  #=> [1, 2, 2, 1]

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

Um arr zu mutieren:

h = removals.group_by(&:itself).transform_values(&:count)
arr.replace(arr.each_with_object([]) { |n,a|
  h.key?(n) && h[n] > 0 ? (h[n] -= 1) : a << n })
  #=> [1, 2, 2, 1]

arr
  #=> [1, 2, 2, 1]

Dies nutzt die 21st Jahrhundertmethode Hash # transform_values ​​ (neu in MRI v2.4), aber man könnte stattdessen schreiben:

h = Hash[removals.group_by(&:itself).map { |k,v| [k,v.size] }]

oder

h = removals.each_with_object(Hash.new(0)) { | n,h| h[n] += 1 }
0
Cary Swoveland
a = [1,1,1,2,2,3]
a.slice!(0) # remove first index
a.slice!(-1) # remove last index
# a = [1,1,2,2] as desired
0
Lyres

Eine einfache Lösung, die ich häufig verwende:

arr = ['remove me',3,4,2,45]

arr[1..-1]

=> [3,4,2,45]
0
The Whiz of Oz