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

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


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


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"

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


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


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


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.


+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

-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
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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.