Удалить подстроку из строки

194

Мне просто интересно, если есть какой-либо метод для удаления строки из другой строки? Что-то вроде этого:

class String
  def remove(s)
    self[s.length, self.length - s.length]
  end
end
Димас
источник

Ответы:

263

Вы можете использовать метод среза:

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

есть не "!" версия также. Более подробную информацию можно найти в документации о других версиях: http://www.ruby-doc.org/core/classes/String.html#method-i-slice-21

Пит
источник
1
Очень элегантно! Вы также можете использовать []s для версии без взрыва.
Матеус Морейра
65
Это имеет плохой побочный эффект возврата удаленного текста (или текста, который искали). Неудачно для цепочки по результату удаления.
Майк
10
Как вы возвращаете нарезанную строку и не влияете на оригинал? Например, если у меня есть «hello world», я хочу нарезать «hello» и вернуть только часть «world» без изменения исходного строкового объекта?
Джабботт
14
@Mike"foobar".tap{|s| s.slice!("foo")}.upcase
Эрнест
7
@bcackerman - deleteне будет работать, так как удаляет все символы, которые вы передаете:'hello world'.delete('hello') #=> ' wrd'
ржавый
166

Как насчет str.gsub("subString", "") проверить Ruby Doc

Пиюш Матту
источник
38
subбыло бы более подходящим, чем gsub, поскольку OP хочет удалить только подстроку из начала строки, а не всю строку (см. его пример кода). И использование регулярного выражения, как это, было бы лучше: str.sub(/^subString/, '')- потому что это гарантирует, что подстрока будет определенно удалена только с самого начала.
Алекс Д
@AlexD Было бы лучше использовать регулярное выражение, но это опасно, если мы не можем быть уверены, subStringчто в нем нет специальных символов регулярного выражения.
Дэвид Моулз
@DavidMoles, в данном случае, /^subString/является литералом, поэтому мы можем быть уверены, что он не содержит метасимволов. Если вы подставляя некоторую другую строку в регулярное выражение, вы можете сделать это: /#{Regexp.escape(str)}/.
Алекс Д
В ответ да, но не в вопросе ОП. Спасибо за указатель на Regexp.escape(), хотя.
Дэвид Моулз
106

Если это конец строки, вы также можете использовать chomp:

"hello".chomp("llo")     #=> "he"
В ожидании Dev ...
источник
если выражение было a.chomp ("llo"), chomp! точнее.
Фернандо Гонсалес Санчес
1
Это чище, чем ломтик !, так как не имеет побочных эффектов.
Арди Арам
5
Если это начало строки, вы также можете использовать chompв сочетании с reverse:"hello".reverse.chomp("he".reverse).reverse #=> "llo"
amoebe
45

Если у вас есть только одно вхождение целевой строки, вы можете использовать:

str[target] = ''

или

str.sub(target, '')

Если у вас есть несколько случаев использования цели:

str.gsub(target, '')

Например:

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 "

Если вам нужно сделать замену на месте, используйте "!"версии gsub!и sub!.

жестяной человек
источник
2
Рубин это весело! очень приятно видеть такие вещи, как:asdf['bar'] = ''
Питер Буткович
1
Я бы не назвал это «забавой» - возможно, не интуитивным.
Jmoney38
31

Если вы используете Rails, есть также remove.

Например, "Testmessage".remove("message")дает "Test".

Предупреждение: этот метод удаляет все вхождения

edwardmp
источник
1
Это не ванильный ответ Ruby, но принятый ответ не совсем то, что ищет большинство людей. К сожалению, sliceметод не возвращает отрезанную часть строки, он возвращает «нож»
Дилан Пирс,
1
@DylanPierce довольно легко реализовать функцию, которая делает это с помощьюslice! def gimme_the_slice(my_string, my_slice) my_string.slice!(my_slice) my_string
Bennett Talpers
1
Ах да, взбучка - это то, как Ruby модифицирует существующую переменную. Спасибо @BennettTalpers
Дилан Пирс
27

Ruby 2.5+

Если ваша подстрока находится в начале или в конце строки, то Ruby 2.5 представил методы для этого:

  • delete_prefix для удаления подстроки из начала строки
  • delete_suffix для удаления подстроки из конца строки
Игорь Дроздов
источник
1

Если я правильно интерпретирую, этот вопрос, по-видимому, требует что-то вроде операции минус (-) между строками, то есть противоположности встроенной операции плюс (+) (конкатенация).

В отличие от предыдущих ответов, я пытаюсь определить такую ​​операцию, которая должна подчиняться свойству:

ЕСЛИ c = a + b ТО c - a = b И c - b = a

Нам нужно всего три встроенных метода Ruby:

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

Я не буду объяснять, как это работает, потому что это легко понять, запуская один метод за раз.

Вот подтверждение концепции кода:

# 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

Последний совет, если вы используете последнюю версию Ruby (> = 2.0): используйте Refinements вместо Monkey-Patching String, как в предыдущем примере.

Это так же просто, как:

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

и добавьте using MinusStringперед блоками, где вам это нужно.

Клаудио Флореани
источник
+1 за понятия уточнений. В то время как класс String для monkey-patching, вероятно, является излишним для этого варианта использования, иногда нам все-таки приходится вносить изменения в monkey-patch, и концепция усовершенствований в нем действительно сияет.
wondersz1
-2

вот что я бы сделал

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

Отформатирован в несколько строк:

class String
    def remove!(start_index, end_index)
        (end_index - start_index + 1).times{ self.slice! start_index }
        self
    end 
end
JayTarka
источник
-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
источник
1
Почему так много павших голосов? что ты сделал не так .. может быть слишком широко
zee
ОП не попросил удалить Öнапример.
Юлиан