从字符串中删除子字符串


193

我只是想知道是否有任何方法可以从另一个字符串中删除字符串?像这样:

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

Answers:


263

您可以使用slice方法:

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

有一个非“!” 版本。在其他版本的文档中也可以找到更多信息:http : //www.ruby-doc.org/core/classes/String.html#method-i-slice-21


1
十分优雅!您也可以将[]s用于非爆炸版本。
Matheus Moreira'3

65
返回删除的文本(或搜索的文本)有不利的副作用。不幸的是链接删除结果。
麦克,时间

10
如何返回切片后的字符串且不影响原始字符串?例如,如果我有“ hello world”,我想切片“ hello”并仅返回“ world”部分,而无需修改原始字符串对象?
jhabbott 2011年

14
@Mike"foobar".tap{|s| s.slice!("foo")}.upcase
欧内斯特(Ernest)

7
@bcackerman- delete不起作用,因为它会删除您传入的所有字符:'hello world'.delete('hello') #=> ' wrd'
生锈的

165

如何str.gsub("subString", "") 查看Ruby Doc


38
sub会比更为合适gsub,因为OP只想从字符串的开头而不是整个字符串中删除子字符串(请看他的示例代码)。像这样使用正则表达式会更好:str.sub(/^subString/, '')-因为它确保绝对仅从开始就删除子字符串。
Alex D

@AlexD使用正则表达式会更好,但是如果我们不确定subString是否不包含任何正则表达式特殊字符,这将很危险。
大卫·摩尔

在这种情况下,@ DavidMoles /^subString/是一个文字,因此我们可以确定它不包含任何元字符。如果要将其他字符串替换为正则表达式,则可以执行以下操作:/#{Regexp.escape(str)}/
Alex D

答案是肯定的,但不是OP的问题。不过,感谢您指向的指针Regexp.escape()
David Moles

105

如果它是字符串的结尾,则也可以使用chomp

"hello".chomp("llo")     #=> "he"

如果表达式是a.chomp(“ llo”),请加油!更精确。
费尔南多·冈萨雷斯·桑切斯

1
这比切片干净!因为它没有副作用。
Ardee Aram

5
如果它是从字符串的开头开始,您还可以chompreverse以下内容结合使用:"hello".reverse.chomp("he".reverse).reverse #=> "llo"
amoebe '17

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'] = ''
Peter Butkovic 2014年

1
我不会称其为“有趣”-也许是非直觉的。
Jmoney38 '19

31

如果您使用的是Rails,那么还可以remove

例如"Testmessage".remove("message")产量"Test"

警告:此方法会删除所有出现的事件


1
这不是一个很好的Ruby答案,但是公认的答案并不是大多数人想要的。不幸的是,该slice方法没有返回被切开的字符串的一部分,而是返回了“刀”
Dylan Pierce

1
@DylanPierce,使用此功能实现此功能非常容易slice! def gimme_the_slice(my_string, my_slice) my_string.slice!(my_slice) my_string
Bennett Talpers

1
没错,Ruby是如何修改现有变量的。感谢@BennettTalpers
Dylan Pierce



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类对于这种用例来说可能是一个过大的杀伤力,但有时我们确实需要用猴子修补的东西,而完善的概念确实令人眼前一亮。
wonders1

-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 2016年

例如,OP并未要求删除Ö
Iulian Onofrei
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.