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


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"

если выражение было 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".

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


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

-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
Почему так много павших голосов? что ты сделал не так .. может быть слишком широко
— zee

ОП не попросил удалить Öнапример.
— Юлиан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.