Entfernen Sie die Teilzeichenfolge aus der Zeichenfolge

193

Ich frage mich nur, ob es eine Methode gibt, um eine Zeichenfolge aus einer anderen Zeichenfolge zu entfernen. Etwas wie das:

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

Antworten:

263

Sie können die Slice-Methode verwenden:

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

es gibt ein nicht '!' Version auch. Weitere Informationen finden Sie auch in der Dokumentation zu anderen Versionen: http://www.ruby-doc.org/core/classes/String.html#method-i-slice-21

Pete
quelle
1
Sehr elegant! Sie können []s auch für die Non-Bang-Version verwenden.
Matheus Moreira
65
Dies hat einen schlechten Nebeneffekt bei der Rückgabe des gelöschten Textes (oder des gesuchten Textes). Leider für die Verkettung des Ergebnisses der Löschung.
Mike
10
Wie können Sie die geschnittene Zeichenfolge zurückgeben und das Original nicht beeinflussen? Wenn ich beispielsweise "Hallo Welt" habe, möchte ich "Hallo" in Scheiben schneiden und nur den Teil "Welt" zurückgeben, ohne das ursprüngliche Zeichenfolgenobjekt zu ändern.
Jhabbott
14
@ Mike"foobar".tap{|s| s.slice!("foo")}.upcase
Ernest
7
@bcackerman - deletewürde nicht funktionieren, da es alle Zeichen löscht, die Sie übergeben:'hello world'.delete('hello') #=> ' wrd'
rostig
165

Wie wäre es mit str.gsub("subString", "") dem Ruby Doc

Piyush Mattoo
quelle
38
subwäre angemessener als gsub, da das OP nur den Teilstring vom Anfang des Strings entfernen möchte , nicht den gesamten String (siehe seinen Beispielcode). Und die Verwendung eines solchen regulären Ausdrucks wäre besser: str.sub(/^subString/, '')- weil dadurch sichergestellt wird, dass der Teilstring definitiv nur von Anfang an entfernt wird.
Alex D
@AlexD Die Verwendung eines regulären Ausdrucks wäre besser, aber es ist gefährlich, wenn wir nicht sicher subStringsind, dass keine regulären Ausdruckszeichen enthalten sind.
David Moles
@DavidMoles ist in diesem Fall /^subString/ein Literal, daher können wir sehr sicher sein, dass es keine Metazeichen enthält. Wenn Sie eine andere Zeichenfolge durch eine Regex ersetzen, können Sie Folgendes tun : /#{Regexp.escape(str)}/.
Alex D
In der Antwort ja, aber nicht in der Frage des OP. Vielen Dank für den Hinweis auf Regexp.escape().
David Moles
105

Wenn es das Ende der Zeichenfolge ist, können Sie auch Folgendes verwenden chomp:

"hello".chomp("llo")     #=> "he"
Warten auf Dev ...
quelle
Wenn der Ausdruck a.chomp ("llo") war, chomp! ist genauer.
Fernando Gonzalez Sanchez
1
Dies ist sauberer als Slice!, Da dies keine Nebenwirkungen hat.
Ardee Aram
5
Wenn es vom Anfang der Zeichenfolge ist, können Sie auch chompin Kombination mit verwenden reverse:"hello".reverse.chomp("he".reverse).reverse #=> "llo"
Amöbe
45

Wenn Sie nur ein Vorkommen der Zielzeichenfolge haben, können Sie Folgendes verwenden:

str[target] = ''

oder

str.sub(target, '')

Wenn Sie mehrere Ziele verwenden:

str.gsub(target, '')

Zum Beispiel:

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 "

Wenn Sie direkte Ersetzungen vornehmen müssen, verwenden Sie die "!"Versionen von gsub!und sub!.

der Blechmann
quelle
2
Rubin macht Spaß! Ich genieße es wirklich Dinge zu sehen wie:asdf['bar'] = ''
Peter Butkovic
1
Ich würde das nicht "Spaß" nennen - vielleicht nicht intuitiv.
Jmoney38
31

Wenn Sie Rails verwenden, gibt es auch remove.

ZB "Testmessage".remove("message")ergibt "Test".

Warnung: Diese Methode entfernt alle Vorkommen

edwardmp
quelle
1
Dies ist keine Vanille-Ruby-Antwort, aber die akzeptierte Antwort ist nicht ganz das, wonach die meisten Menschen suchen. Leider gibt die sliceMethode nicht den Teil der Schnur zurück, der in Scheiben geschnitten wurde, sondern das "Messer"
Dylan Pierce
1
@ DylanPierce es ist ziemlich einfach, eine Funktion zu implementieren, die dies mitslice! def gimme_the_slice(my_string, my_slice) my_string.slice!(my_slice) my_string
Bennett Talpers
1
Ah, das stimmt, durch Ruby-ifying ändert Ruby die vorhandene Variable. Danke @BennettTalpers
Dylan Pierce
26

Ruby 2.5+

Wenn sich Ihre Teilzeichenfolge am Anfang am Ende einer Zeichenfolge befindet, hat Ruby 2.5 die folgenden Methoden eingeführt:

  • delete_prefix zum Entfernen eines Teilstrings vom Anfang der Zeichenfolge
  • delete_suffix zum Entfernen eines Teilstrings vom Ende der Zeichenfolge
Igor Drozdov
quelle
1

Wenn ich richtig interpretiere, scheint diese Frage nach einer Minusoperation (-) zwischen Zeichenfolgen zu fragen, dh nach dem Gegenteil der integrierten Plusoperation (+) (Verkettung).

Im Gegensatz zu den vorherigen Antworten versuche ich, eine solche Operation zu definieren, die der Eigenschaft gehorchen muss:

WENN c = a + b DANN c - a = b UND c - b = a

Wir benötigen nur drei integrierte Ruby-Methoden, um dies zu erreichen:

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

Ich werde nicht erklären, wie es funktioniert, da es leicht zu verstehen ist, jeweils eine Methode auszuführen.

Hier ist ein Proof-of-Concept-Code:

# 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

Ein letzter Ratschlag, wenn Sie eine aktuelle Ruby-Version verwenden (> = 2.0): Verwenden Sie Verfeinerungen anstelle von Affen-Patching-Zeichenfolgen wie im vorherigen Beispiel.

Es ist so einfach wie:

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

und fügen Sie using MinusStringvor den Blöcken hinzu, wo Sie es brauchen.

Claudio Floreani
quelle
+1 für die Konzepte der Verfeinerung. Während die String-Klasse zum Affen-Patchen wahrscheinlich ein Overkill für diesen Anwendungsfall ist, müssen wir manchmal Dinge zum Affen-Patchen und das Konzept der Verfeinerungen wirklich zum Leuchten bringen.
Wondersz1
-2

Hier ist was ich tun würde

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

In mehreren Zeilen formatiert:

class String
    def remove!(start_index, end_index)
        (end_index - start_index + 1).times{ self.slice! start_index }
        self
    end 
end
JayTarka
quelle
-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
quelle
1
Warum so viele Abstimmungen? was hast du falsch gemacht .. vielleicht zu breit
zee
Das OP hat Özum Beispiel nicht darum gebeten, es zu entfernen .
Iulian Onofrei