Rimuovere la sottostringa dalla stringa


194

Mi chiedo solo se esiste un metodo per rimuovere la stringa da un'altra stringa? Qualcosa come questo:

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

Risposte:


263

Puoi usare il metodo slice:

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

c'è un non '!' anche la versione. Maggiori informazioni sono disponibili nella documentazione anche su altre versioni: http://www.ruby-doc.org/core/classes/String.html#method-i-slice-21


1
Molto elegante! Puoi anche usare []s per la versione non bang.
Matheus Moreira,

65
Ciò ha un brutto effetto collaterale nel restituire il testo eliminato (o il testo cercato). Peccato per il concatenamento sul risultato della cancellazione.
Mike,

10
Come si restituisce la stringa tagliata e non influisce sull'originale? Ad esempio, se ho "ciao mondo", voglio tagliare "ciao" e restituire solo la parte "mondo", senza modificare l'oggetto stringa originale?
Jhabbott,

14
@Mike"foobar".tap{|s| s.slice!("foo")}.upcase
Ernest

7
@bcackerman - deletenon funzionerebbe, poiché cancella tutti i personaggi in cui passi:'hello world'.delete('hello') #=> ' wrd'
arrugginito,

166

Che ne dite di str.gsub("subString", "") controllare il Ruby Doc


38
subsarebbe più appropriato di gsub, poiché l'OP vuole solo rimuovere la sottostringa dall'inizio della stringa, non tutta la stringa (guarda il suo codice di esempio). E usare una regex, come questa, sarebbe meglio: str.sub(/^subString/, '')- perché assicura che la sottostringa verrà definitivamente rimossa solo dall'inizio.
Alex D,

@AlexD Usare una regex sarebbe meglio, ma è pericoloso se non possiamo essere sicuri subStringche non includa caratteri speciali regex.
David Moles,

@DavidMoles, in questo caso, /^subString/è letterale, quindi possiamo essere certi che non includa metacaratteri. Se si sta sostituendo qualche altra stringa in un'espressione regolare, si può fare questo: /#{Regexp.escape(str)}/.
Alex D,

Nella risposta sì, ma non nella domanda del PO. Grazie per il puntatore Regexp.escape(), però.
David Moles,

106

Se è la fine della stringa, puoi anche usare chomp:

"hello".chomp("llo")     #=> "he"

se l'espressione era a.chomp ("llo"), chomp! è più preciso.
Fernando Gonzalez Sanchez,

1
Questo è più pulito di slice !, in quanto non ha effetti collaterali.
Ardee Aram,

5
Se è dall'inizio della stringa, puoi anche utilizzare chompin combinazione con reverse:"hello".reverse.chomp("he".reverse).reverse #=> "llo"
amoebe

45

Se hai una sola occorrenza della stringa di destinazione puoi usare:

str[target] = ''

o

str.sub(target, '')

Se hai più occorrenze di destinazione d'uso:

str.gsub(target, '')

Per esempio:

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 "

Se è necessario eseguire sostituzioni sul posto, utilizzare le "!"versioni di gsub!e sub!.


2
ruby è divertente! mi piace molto vedere cose come:asdf['bar'] = ''
Peter Butkovic,

1
Non lo definirei "divertente", forse non intuitivo.
Jmoney38

31

Se stai usando Rails c'è anche remove.

Ad esempio "Testmessage".remove("message")rese "Test".

Attenzione: questo metodo rimuove tutte le occorrenze


1
Questa non è una risposta rubino alla vaniglia, ma la risposta accettata non è proprio quello che la maggior parte delle persone sta cercando. Sfortunatamente il slicemetodo non restituisce la parte della stringa che viene tagliata, ma restituisce il "coltello"
Dylan Pierce,

1
@DylanPierce è abbastanza facile implementare una funzione che lo fa usandoslice! def gimme_the_slice(my_string, my_slice) my_string.slice!(my_slice) my_string
Bennett Talpers,

1
Ah esatto, bang-ifying è il modo in cui Ruby modifica la variabile esistente. Grazie @BennettTalpers
Dylan Pierce,

27

Rubino 2.5+

Se la sottostringa si trova all'inizio della fine di una stringa, Ruby 2.5 ha introdotto i metodi per questo:

  • delete_prefix per la rimozione di una sottostringa dall'inizio della stringa
  • delete_suffix per la rimozione di una sottostringa dalla fine della stringa


1

Se sto interpretando bene, questa domanda sembra richiedere qualcosa come un'operazione meno (-) tra le stringhe, ovvero l'opposto dell'operazione incorporata più (+) (concatenazione).

A differenza delle risposte precedenti, sto cercando di definire un'operazione del genere che deve obbedire alla proprietà:

SE c = a + b POI c - a = b AND c - b = a

Abbiamo bisogno solo di tre metodi Ruby integrati per raggiungere questo obiettivo:

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

Non spiegherò come funziona perché può essere facilmente compreso eseguendo un metodo alla volta.

Ecco un codice di prova del concetto:

# 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

Un'ultima parola di consiglio se stai usando una versione recente di Ruby (> = 2.0): usa i perfezionamenti invece della stringa di patch delle scimmie come nell'esempio precedente.

È facile come:

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

e aggiungi using MinusStringprima dei blocchi dove ne hai bisogno.


+1 per i concetti di perfezionamento. Mentre la classe String di patch di scimmia è probabilmente un sovraccarico per questo caso d'uso, a volte dobbiamo scimmiottare cose di scimmia e il concetto di raffinatezza brilla davvero.
Wondersz, 1

-2

ecco cosa farei

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!" 

Formattato su più righe:

class String
    def remove!(start_index, end_index)
        (end_index - start_index + 1).times{ self.slice! start_index }
        self
    end 
end

-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

1
Perché così tanti voti negativi? cosa hai fatto di sbagliato .. forse troppo ampio
zee

L'OP non ha chiesto di rimuovere Öad esempio.
Iulian Onofrei
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.