Hapus substring dari string

193

Saya hanya ingin tahu apakah ada metode untuk menghapus string dari string lain? Sesuatu seperti ini:

class String
  def remove(s)
    self[s.length, self.length - s.length]
  end
end
demo
sumber

Jawaban:

263

Anda dapat menggunakan metode slice:

a = "foobar"
a.slice! "foo"
=> "foo"
a
=> "bar"

ada yang bukan '!' versi juga. Info lebih lanjut dapat dilihat di dokumentasi tentang versi lain juga: http://www.ruby-doc.org/core/classes/String.html#method-i-slice-21

Pete
sumber
1
Sangat elegan! Anda juga dapat menggunakan []s untuk versi non-bang.
Matheus Moreira
65
Ini memiliki efek samping buruk mengembalikan teks yang dihapus (atau teks yang dicari). Sangat disayangkan karena rantai pada hasil penghapusan.
Mike
10
Bagaimana Anda mengembalikan string yang diiris dan tidak memengaruhi yang asli? Sebagai contoh jika saya memiliki "halo dunia", saya ingin mengiris "halo" dan mengembalikan hanya bagian "dunia", tanpa memodifikasi objek string asli?
jhabbott
14
@ Mike"foobar".tap{|s| s.slice!("foo")}.upcase
Ernest
7
@bcackerman - deletetidak akan berfungsi, karena menghapus semua karakter yang Anda masukkan :'hello world'.delete('hello') #=> ' wrd'
rusty
165

Bagaimana str.gsub("subString", "") dengan Ruby Doc

Piyush Mattoo
sumber
38
subakan lebih tepat daripada gsub, karena OP hanya ingin menghapus substring dari awal string, tidak semua melalui string (lihat kode contohnya). Dan menggunakan regex, seperti ini, akan lebih baik: str.sub(/^subString/, '')- karena memastikan bahwa substring pasti akan dihapus hanya dari awal.
Alex D
@AlexD Menggunakan regex akan lebih baik, tetapi berbahaya jika kita tidak yakin subStringtidak memasukkan karakter khusus regex.
David Moles
@DavidMoles, dalam hal ini, /^subString/adalah literal, jadi kita bisa sangat yakin itu tidak termasuk karakter metachar. Jika Anda mengganti beberapa string lain dalam regex, Anda dapat melakukan ini: /#{Regexp.escape(str)}/.
Alex D
Dalam jawabannya, ya, tetapi tidak dalam pertanyaan OP. Terima kasih atas penunjuknya Regexp.escape().
David Moles
105

Jika ini adalah akhir dari string, Anda juga dapat menggunakan chomp:

"hello".chomp("llo")     #=> "he"
Menunggu Dev ...
sumber
jika ekspresinya adalah a.chomp ("llo"), chomp! lebih tepat.
Fernando Gonzalez Sanchez
1
Ini lebih bersih daripada irisan !, karena ini tidak memiliki efek samping.
Ardee Aram
5
Jika dari awal string, Anda juga dapat menggunakan chompdalam kombinasi dengan reverse:"hello".reverse.chomp("he".reverse).reverse #=> "llo"
amoebe
45

Jika Anda hanya memiliki satu kemunculan string target yang dapat Anda gunakan:

str[target] = ''

atau

str.sub(target, '')

Jika Anda memiliki beberapa kejadian penggunaan target:

str.gsub(target, '')

Misalnya:

asdf = 'foo bar'
asdf['bar'] = ''
asdf #=> "foo "

asdf = 'foo bar'
asdf.sub('bar', '') #=> "foo "
asdf = asdf + asdf #=> "foo barfoo bar"
asdf.gsub('bar', '') #=> "foo foo "

Jika Anda perlu melakukan penggantian di tempat, gunakan "!"versi gsub!dan sub!.

Manusia Timah
sumber
2
ruby itu menyenangkan! sangat menikmati melihat hal-hal seperti:asdf['bar'] = ''
Peter Butkovic
1
Saya tidak akan menyebut itu "menyenangkan" - mungkin tidak intuitif.
Jmoney38
31

Jika Anda menggunakan Rails, ada juga remove .

Misalnya "Testmessage".remove("message")hasil"Test" .

Peringatan: metode ini menghilangkan semua kejadian

edwardmp
sumber
1
Ini bukan jawaban vanilla Ruby, tetapi jawaban yang diterima tidak sesuai dengan yang dicari oleh kebanyakan orang. Sayangnya slicemetode ini tidak mengembalikan bagian dari tali yang diiris, itu mengembalikan "pisau"
Dylan Pierce
1
@DylanPierce sangat mudah untuk mengimplementasikan fungsi yang menggunakan ituslice! def gimme_the_slice(my_string, my_slice) my_string.slice!(my_slice) my_string
Bennett Talpers
1
Ah itu benar, bang-ifying adalah bagaimana Ruby memodifikasi variabel yang ada. Terima kasih @BennettTalpers
Dylan Pierce
26

Ruby 2.5+

Jika substring Anda ada di awal di akhir string, maka Ruby 2.5 telah memperkenalkan metode untuk ini:

Igor Drozdov
sumber
1

Jika saya menafsirkan dengan benar, pertanyaan ini sepertinya menanyakan sesuatu seperti operasi minus (-) di antara string, yaitu kebalikan dari operasi built-in plus (+) (gabungan).

Tidak seperti jawaban sebelumnya, saya mencoba mendefinisikan operasi yang harus mematuhi properti:

JIKA c = a + b THEN c - a = b DAN c - b = a

Kami hanya membutuhkan tiga metode Ruby bawaan untuk mencapai ini:

'abracadabra'.partition('abra').values_at(0,2).join == 'cadabra'.

Saya tidak akan menjelaskan cara kerjanya karena dapat dengan mudah dipahami menjalankan satu metode pada satu waktu.

Berikut ini adalah bukti kode konsep:

# minus_string.rb
class String
  def -(str)
    partition(str).values_at(0,2).join
  end
end

# Add the following code and issue 'ruby minus_string.rb' in the console to test
require 'minitest/autorun'

class MinusString_Test < MiniTest::Test

  A,B,C='abra','cadabra','abracadabra'

  def test_C_eq_A_plus_B
    assert C == A + B
  end

  def test_C_minus_A_eq_B
    assert C - A == B
  end

  def test_C_minus_B_eq_A
    assert C - B == A
  end

end

Satu kata nasihat terakhir jika Anda menggunakan versi Ruby terbaru (> = 2.0): gunakan Penyempitan alih-alih String monyet-patching seperti pada contoh sebelumnya.

Semudah:

module MinusString
  refine String do
    def -(str)
      partition(str).values_at(0,2).join
    end
  end
end

dan tambahkan using MinusStringsebelum blok di mana Anda membutuhkannya.

Claudio Floreani
sumber
+1 untuk konsep penyempurnaan. Sementara kelas String monyet-patching mungkin merupakan pembunuhan berlebihan untuk kasus penggunaan ini, kadang-kadang kita harus menambal hal-hal dan konsep perbaikan benar-benar bersinar di dalamnya.
wondersz1
-2

inilah yang akan saya lakukan

2.2.1 :015 > class String; def remove!(start_index, end_index) (end_index - start_index + 1).times{ self.slice! start_index }; self end; end;
2.2.1 :016 >   "idliketodeleteHEREallthewaytoHEREplease".remove! 14, 32
 => "idliketodeleteplease" 
2.2.1 :017 > ":)".remove! 1,1
 => ":" 
2.2.1 :018 > "ohnoe!".remove! 2,4
 => "oh!" 

Diformat dalam beberapa baris:

class String
    def remove!(start_index, end_index)
        (end_index - start_index + 1).times{ self.slice! start_index }
        self
    end 
end
JayTarka
sumber
-7
def replaceslug
  slug = "" + name
    @replacements = [
      [ "," , ""],
      [ "\\?" , ""],
      [ " " , "-"],
      [ "'" , "-"],
      [ "Ç" , "c"],
      [ "Ş" , "s"],
      [ "İ" , "i"],
      [ "I" , "i"],
      [ "Ü" , "u"],
      [ "Ö" , "o"],
      [ "Ğ" , "g"],
      [ "ç" , "c"],
      [ "ş" , "s"],
      [ "ı" , "i"],
      [ "ü" , "u"],
      [ "ö" , "o"],
      [ "ğ" , "g"],
    ]
  @replacements.each do |pair|
    slug.gsub!(pair[0], pair[1])
  end
  self.slug = slug.downcase
end
Ilkay
sumber
1
Mengapa begitu banyak suara? apa yang Anda lakukan salah .. terlalu luas mungkin
zee
OP tidak meminta untuk menghapus Ömisalnya.
Iulian Onofrei