Bagaimana saya bisa menghapus satu elemen dari array berdasarkan nilai

343

Saya memiliki berbagai elemen di Ruby

[2,4,6,3,8]

Saya perlu menghapus elemen dengan nilai 3misalnya

Bagaimana aku melakukan itu?

Tamik Soziev
sumber
saya bertanya-tanya mengapa delete array.delete(3)tidak bekerja di dalam ruby ​​on rails controller
ImranNaqvi
2
mungkin karena active recordmetodedelete
ImranNaqvi

Jawaban:

481

Saya pikir saya sudah menemukan jawabannya:

a = [3, 2, 4, 6, 3, 8]
a.delete(3)
#=> 3
a
#=> [2, 4, 6, 8]
Tamik Soziev
sumber
189
Saya pribadi suka [1, 2, 3, 4, 5] - [3]yang hasil => [1, 2, 4, 5]dari irb.
Travis
24
Bagaimana jika ada beberapa entri 3 dan kami hanya ingin menghapus satu saja? (ini terkait jadi menanyakan ini di sini mungkin yang terbaik)
Navneet
113
Hanya kepala yang .delete () akan mengembalikan nilai yang dihapus, bukan array yang dimodifikasi dengan nilai yang dihapus.
Joshua Pinter
23
Konsekuensi lain yang perlu dipertimbangkan adalah yang deletemengubah array yang mendasarinya sedangkan -membuat array baru (yang dikembalikan kepada Anda) tanpa nilai yang dihapus. Tergantung pada kasus penggunaan Anda, pendekatan mana pun mungkin masuk akal.
srt32
2
@ user3721428, hapus (3) tidak merujuk ke elemen di posisi 3 tetapi menghapus elemen yang cocok dengan bilangan bulat 3. Ini akan menghapus semua kemunculan 3 dan tidak ada hubungannya dengan indeks array atau posisi.
bkunzi01
226

Meminjam dari Travis di komentar, ini adalah jawaban yang lebih baik:

Saya pribadi suka [1, 2, 7, 4, 5] - [7]yang hasil => [1, 2, 4, 5]dariirb

Saya mengubah jawabannya dengan melihat bahwa 3 adalah elemen ketiga dalam contoh arraynya. Ini dapat menyebabkan beberapa kebingungan bagi mereka yang tidak menyadari bahwa 3 berada di posisi 2 dalam array.

Abram
sumber
21
Seperti yang ditunjukkan olehrtrt32 dalam jawaban, ada perbedaan penting untuk dibuat antara menggunakan .deletedan -. .deleteakan mengembalikan nilai yang dihapus dari Array, jika ada; -tidak akan. Jadi [ 1, 2, 3 ] - [ 2 ]akan kembali [ 1, 3 ], sementara [ 1, 2, 3 ].delete( 2 )akan kembali 2.
Argus9
5
array - subArraytidak akan berfungsi untuk Array of Arays , tetapi array.delete(subArray)akan berhasil.
Sachin
20
Perbedaan yang sangat penting antara [1,2,3] - [2]dan [1,2,3].delete(2)adalah deletemetode memodifikasi array asli , sementara [1,2,3] - [3]menciptakan array baru .
Timothy Kovalev
Subarrays ulang (@ komentar Sachin di atas) "Tentu saja", Anda hanya perlu mendapatkan notasi yang benar: [1,2,[2],2,3,4] - [2]memberi Anda [1, [2], 3, 4], tetapi [1,2,[2],2,3,4] - [[2]]memberi Anda [1, 2, 2, 3, 4]. :-)
Tom Hundt
69

Pilihan lain:

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

a -= [3]

yang mengakibatkan

=> [2, 4, 6, 8] 
Steve
sumber
50

Saya tidak yakin apakah ada yang menyatakan ini, tetapi Array.delete () dan - = value akan menghapus setiap instance dari nilai yang diteruskan ke dalam Array. Untuk menghapus instance pertama dari elemen tertentu Anda bisa melakukan sesuatu seperti

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

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

Mungkin ada cara yang lebih sederhana. Saya tidak mengatakan ini adalah praktik terbaik, tetapi ini adalah sesuatu yang harus diakui.

Scott
sumber
1
Saya sedang mencari cara untuk melakukan ini dan hanya menghapus satu instance dari memetikan elemen duplikat dan ini bekerja dengan baik!
xeroshogun
Saya pikir jawaban ini salah, hanya karena arr.index () bisa perginil
windmaomao
32

Dengan asumsi Anda ingin menghapus 3 dengan nilai di banyak tempat dalam array, saya pikir cara ruby ​​untuk melakukan tugas ini adalah dengan menggunakan metode delete_if:

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

Anda juga dapat menggunakan delete_if dalam menghapus elemen dalam skenario 'array array'.

Semoga ini menyelesaikan kueri Anda

Sayan
sumber
25

Saya suka -=[4]cara yang disebutkan dalam jawaban lain untuk menghapus elemen yang nilainya 4.

Tetapi ada cara ini:

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

disebutkan di suatu tempat di " Operasi Array Dasar ", setelah itu menyebutkan mapfungsi.

barlop
sumber
Tapi tidak bisakah Anda menggunakan.delete(6)
Zac
@Zac tentu saja tapi jawaban telah disebutkan (seperti memiliki sangat ringkas -=cara a-=[4]yaitu a=a-[4]. [3,4]-[4], Yang aku bilang aku suka), tapi saya ingin menyebutkan cara lain mungkin.
barlop
Metode ini juga memiliki keuntungan mengembalikan array daripada elemen yang dihapus.
P.
22

Anda cukup menjalankan:

[2,4,6,3,8].delete(3)
rilutham
sumber
20

A di .delete_at(3) 3sini adalah posisinya.

Tebing Sawo
sumber
15

Inilah beberapa tolok ukur:

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

Dan lagi dengan array yang lebih besar yang mengandung banyak duplikat:

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

Dan bahkan lebih besar dengan duplikat lebih banyak:

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
Manusia Timah
sumber
7
Jadi, apa yang terbaik dari itu? :)
Kirby
8

Saya meningkatkan solusi Niels

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

Sekarang kamu bisa menggunakannya

[1, 2, 3, 4].except(3, 4) # return [1, 2]
[1, 2, 3, 4].except(4)    # return [1, 2, 3]
Rodrigo Mendonça
sumber
Solusi Anda tidak berfungsi pada irbkonsol 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
Untuk mendeklarasikan di IRB, Anda perlu menambahkan metode ke Array class Array; def except(*values); self - values; end; end.
Mark Swardstrom
3

Anda juga bisa menambal monyet. Saya tidak pernah mengerti mengapa Ruby memiliki exceptmetode untuk Hashtetapi tidak untuk Array:

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

Sekarang Anda bisa melakukannya:

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

Atau:

[1,3,7,"436",354,nil].except([354, 1]) #=> [3,7,"436",nil]
Niels Kristian
sumber
1
Anda tidak perlu value.kind_of(Array)ujian. Gunakan saja self - Array(value).
Sasgorilla
3

Jadi ketika Anda memiliki beberapa kemunculan 3 dan Anda hanya ingin menghapus kemunculan pertama dari 3, Anda bisa melakukan beberapa hal seperti di bawah ini.

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
sumber
3

Penghapusan kejadian pertama yang tidak merusak:

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

Jika Anda juga ingin membuat operasi penghapusan ini dapat dilakukan rantai, sehingga Anda dapat menghapus beberapa item dan terus melakukan operasi chaining pada array yang dihasilkan, gunakan tap:

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

Kompilasi semua opsi berbeda untuk dihapus di ruby

delete - Menghapus elemen yang cocok berdasarkan nilai. Jika lebih dari satu nilai cocok, itu akan menghapus semua. Jika Anda tidak peduli dengan jumlah kejadian atau yakin tentang kejadian tunggal, gunakan metode ini.

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

delete_at - Menghapus elemen pada indeks yang diberikan. Jika Anda tahu indeksnya gunakan metode ini.

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

delete_if - Menghapus setiap elemen yang bloknya benar. Ini akan mengubah array. Array berubah secara instan saat blok dipanggil.

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

tolak - Ini akan mengembalikan array baru dengan elemen yang bloknya salah. Pemesanan dipertahankan dengan ini.

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

menolak! - sama seperti delete_if . Array mungkin tidak berubah secara instan karena blok dipanggil.

Jika Anda ingin menghapus beberapa nilai dari array, opsi terbaik adalah seperti di bawah ini.

a = [2, 3, 7, 4, 6, 21, 13]
b = [7, 21]
a = a - b    # a - [2, 3, 4, 6, 13]
Ankit Agrawal
sumber