Jak mogę usunąć jeden element z tablicy według wartości

343

Mam szereg elementów w Ruby

[2,4,6,3,8]

Muszę 3na przykład usunąć elementy o wartości

Jak mogę to zrobić?

Tamik Soziev
źródło
Zastanawiam się, dlaczego delete array.delete(3)nie działa w kontrolerze Ruby on
Rails
2
może wynikać z active recordmetodydelete
ImranNaqvi,

Odpowiedzi:

481

Myślę, że wymyśliłem to:

a = [3, 2, 4, 6, 3, 8]
a.delete(3)
#=> 3
a
#=> [2, 4, 6, 8]
Tamik Soziev
źródło
189
Ja osobiście jak [1, 2, 3, 4, 5] - [3]co skutkuje => [1, 2, 4, 5]od irb.
Travis,
24
Co jeśli jest wiele wpisów 3 i chcemy usunąć tylko jeden z nich? (jest to powiązane, więc pytanie tutaj może być najlepsze)
Navneet
113
Tylko jedna głowa, że ​​.delete () zwróci usuniętą wartość, a nie zmodyfikowaną tablicę z usuniętą wartością.
Joshua Pinter
23
Inną konsekwencją do rozważenia jest to, że deletemutuje podstawową tablicę, a jednocześnie -tworzy nową tablicę (która jest zwracana do Ciebie) bez usuniętej wartości. W zależności od przypadku użycia każde z tych podejść może mieć sens.
srt32
2
@ user3721428, delete (3) nie odnosi się do elementu w pozycji 3, ale usuwa dowolny element pasujący do liczby całkowitej 3. Usunie wszystkie wystąpienia 3 i nie ma nic wspólnego z indeksem lub pozycją tablic.
bkunzi01
226

Pożyczając od Travisa w komentarzach, to lepsza odpowiedź:

Ja osobiście jak [1, 2, 7, 4, 5] - [7]co skutkuje => [1, 2, 4, 5]odirb

Zmodyfikowałem jego odpowiedź, widząc, że 3 jest trzecim elementem w jego przykładowej tablicy. Może to prowadzić do zamieszania dla tych, którzy nie zdają sobie sprawy, że 3 jest na pozycji 2 w tablicy.

Abram
źródło
21
Jak wskazuje srt32 w odpowiedzi, istnieje ważne rozróżnienie między używaniem .deletea -. .deletezwróci wartość, która została usunięta z tablicy, jeśli taka istnieje; -nie będzie. Więc [ 1, 2, 3 ] - [ 2 ]wróci [ 1, 3 ], a [ 1, 2, 3 ].delete( 2 )wróci 2.
Argus9,
5
array - subArraynie będzie działać dla Array of Arrays , ale array.delete(subArray)zadziała.
Sachin,
21
Bardzo ważną różnicą między [1,2,3] - [2]i [1,2,3].delete(2)jest to, że deletemetoda modyfikuje oryginalną tablicę , a jednocześnie [1,2,3] - [3]tworzy nową tablicę .
Timothy Kovalev
Odnośnie podpólek (komentarz @ Sachina powyżej) „Pewnie, że tak”, wystarczy poprawnie zapisać notację: [1,2,[2],2,3,4] - [2]daje [1, [2], 3, 4], ale [1,2,[2],2,3,4] - [[2]]daje [1, 2, 2, 3, 4]. :-)
Tom Hundt,
69

Inna opcja:

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

a -= [3]

Co skutkuje w

=> [2, 4, 6, 8] 
Steve
źródło
50

Nie jestem pewien, czy ktoś to stwierdził, ale Array.delete () i - = wartość usunie każde wystąpienie wartości przekazanej do niej w tablicy. Aby usunąć pierwsze wystąpienie określonego elementu, możesz zrobić coś takiego

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

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

Może być prostszy sposób. Nie twierdzę, że jest to najlepsza praktyka, ale należy ją uznać.

Scott
źródło
1
Szukałem sposobu, aby to zrobić i usunąć tylko jedną instancję elementu incase duplikatów i to działa świetnie!
xeroshogun,
Myślę, że ta odpowiedź jest błędna, po prostu dlatego, że arr.index () może odejśćnil
windmaomao
32

Zakładając, że chcesz usunąć 3 według wartości w wielu miejscach w tablicy, myślę, że rubinowym sposobem wykonania tego zadania byłoby użycie metody delete_if:

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

Możesz także użyć delete_if do usuwania elementów w scenariuszu „tablica tablic”.

Mam nadzieję, że to rozwiąże twoje zapytanie

Sayan
źródło
25

Podoba mi się -=[4]sposób wspomniany w innych odpowiedziach, aby usunąć elementy, których wartość wynosi 4.

Ale jest taki sposób:

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

wspomniany gdzieś w „ Podstawowych operacjach tablicowych ”, po tym jak wspomina o mapfunkcji.

barlop
źródło
Ale nie możesz po prostu użyć.delete(6)
Zac
@Zac oczywiście, ale ta odpowiedź została już wspomniana (podobnie jak bardzo zwięzły -=sposób, a-=[4]tj a=a-[4]. [3,4]-[4]Który, jak powiedziałem, podobało mi się), ale chciałem wspomnieć o innym możliwym sposobie.
barlop
Ta metoda ma również tę zaletę, że zwraca tablicę zamiast usuniętego elementu.
F.Webber
22

Możesz po prostu uruchomić:

[2,4,6,3,8].delete(3)
rilutham
źródło
20

.delete_at(3) 3Tutaj jest pozycja.

Sawo Cliff
źródło
15

Oto kilka punktów odniesienia:

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

I znowu z większą tablicą zawierającą wiele duplikatów:

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

A nawet większy z większą liczbą duplikatów:

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
Blaszany Człowiek
źródło
7
Więc co jest najlepsze? :)
Kirby,
8

Poprawiłem rozwiązanie Nielsa

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

Teraz możesz użyć

[1, 2, 3, 4].except(3, 4) # return [1, 2]
[1, 2, 3, 4].except(4)    # return [1, 2, 3]
Rodrigo Mendonça
źródło
Twoje rozwiązanie nie działa na irbkonsoli 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
Aby zadeklarować w IRB, musisz dodać metodę do Array class Array; def except(*values); self - values; end; end.
Mark Swardstrom
3

Możesz także załatać małpę. Nigdy nie zrozumiałem, dlaczego Ruby ma exceptmetodę, Hashale nie dla Array:

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

Teraz możesz zrobić:

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

Lub:

[1,3,7,"436",354,nil].except([354, 1]) #=> [3,7,"436",nil]
Niels Kristian
źródło
1
Nie potrzebujesz value.kind_of(Array)testu. Po prostu użyj self - Array(value).
Sasgorilla,
3

Więc jeśli masz wiele wystąpień 3 i chcesz tylko usunąć pierwsze wystąpienie 3, możesz po prostu zrobić coś, jak poniżej.

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.
ashan priyadarshana
źródło
3

Nieniszczące usunięcie pierwszego wystąpienia:

a = [2, 4, 6, 3, 8]
n = a.index 3
a.take(n)+a.drop(n+1)
Lori
źródło
2

Jeśli chcesz, aby ta operacja usuwania była łańcuchowa, abyś mógł usunąć jakiś element i kontynuować operacje łańcuchowe na wynikowej tablicy, użyj tap:

[2, 4, 6, 3, 8].tap { |ary| ary.delete(3) }.count #=> 4
dgilperez
źródło
1

Kompilowanie wszystkich różnych opcji usuwania w ruby

delete - usuwa pasujące elementy według wartości. Jeśli więcej niż jedna wartość pasuje, spowoduje to usunięcie wszystkich. Jeśli nie obchodzi Cię liczba wystąpień lub nie masz pewności co do pojedynczego wystąpienia, skorzystaj z tej metody.

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

delete_at - Usuwa element o podanym indeksie. Jeśli znasz indeks, użyj tej metody.

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

delete_if - Usuwa każdy element, dla którego blok jest prawdziwy. Spowoduje to modyfikację tablicy. Tablica zmienia się natychmiast po wywołaniu bloku.

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

odrzucenie - zwróci nową tablicę z elementami, dla których dany blok jest fałszywy. Dzięki temu utrzymywane jest porządkowanie.

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

odrzucać! - to samo co delete_if . Tablica może nie zmienić się natychmiast po wywołaniu bloku.

Jeśli chcesz usunąć wiele wartości z tablicy, najlepszą opcją jest jak poniżej.

a = [2, 3, 7, 4, 6, 21, 13]
b = [7, 21]
a = a - b    # a - [2, 3, 4, 6, 13]
Ankit Agrawal
źródło