Видаліть підрядку з рядка


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
Як повернути нарізаний рядок і не вплинути на оригінал? Наприклад, якщо у мене є "привіт світ", я хочу нарізати "привіт" і повернути лише частину "світу", не змінюючи оригінальний об'єкт рядка?
джабботт

14
@Mike"foobar".tap{|s| s.slice!("foo")}.upcase
Ернест

7
@bcackerman - deleteне вийде, оскільки видаляє всіх персонажів, які ти передаєш :'hello world'.delete('hello') #=> ' wrd'
іржавий

165

Як щодо str.gsub("subString", "") перевірки документа Ruby


38
subбуло б більш доцільно, ніж gsubоскільки ОП хоче лише видалити підрядку з початку рядка, а не все через рядок (дивіться його зразок коду). І використовувати регулярний вираз, як це, було б краще: 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
Це не відповідь ванільної Рубі, але прийнята відповідь не зовсім те, що шукають більшість людей. На жаль, 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

Рубін 2,5+

Якщо ваша підрядка знаходиться на початку в кінці рядка, то Ruby 2.5 ввів методи для цього:

  • delete_prefix для видалення підрядки з початку рядка
  • delete_suffix для видалення підрядки з кінця рядка


1

Якщо я правильно трактую, це питання, схоже, задає щось на зразок мінусу (-) операції між рядками, тобто протилежної вбудованій операції плюс (+) (конкатенація).

На відміну від попередніх відповідей, я намагаюся визначити таку операцію, яка повинна підкорятися властивості:

ЯКЩО c = a + b ТАГО c - a = b AND 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): використовуйте доопрацювання замість String-стрижки мавпи, як у попередньому прикладі.

Це так просто, як:

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

і додайте using MinusStringперед блоками, де вам це потрібно.


+1 для понять уточнення. У той час як клас String-маніпулювання - це, мабуть, надмірний рівень для цього випадку використання, іноді нам доводиться мавпатирувати речі та поняття уточнення насправді світить у цьому.
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.