文字列から部分文字列を削除します


193

別の文字列から文字列を削除する方法があるかどうか疑問に思っていますか?このようなもの:

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
とてもエレガント![]非bangバージョンにはsを使用することもできます。
Matheus Moreira

65
これには、削除されたテキスト(または検索されたテキスト)を返すという悪影響があります。削除の結果を連鎖させるのは残念です。
Mike

10
スライスされた文字列を返し、元の文字列に影響を与えないようにするにはどうすればよいですか?たとえば、「hello world」がある場合、元の文字列オブジェクトを変更せずに、「hello」をスライスして「world」部分だけを返したいですか?
jhabbott、2011年

14
@マイク"foobar".tap{|s| s.slice!("foo")}.upcase
アーネスト

7
@bcackerman - deleteそれはあなたが合格すべての文字を削除するので、動作しません:'hello world'.delete('hello') #=> ' wrd'
さび

165

Ruby Docをstr.gsub("subString", "") 調べてみてはいかがですか


38
subgsubOPは文字列全体ではなく、文字列の先頭から部分文字列を削除するだけなので、より適切です(彼のサンプルコードを見てください)。そして、このような正規表現を使用することはより良いでしょう:str.sub(/^subString/, '')-それは部分文字列が確実に最初からのみ削除されることを保証するためです。
Alex D

@AlexD正規表現を使用することをお勧めしsubStringますが、正規表現の特殊文字が含まれていないことが確実でない場合は危険です。
David Moles

この場合、@ DavidMoles /^subString/はリテラルであるため、メタ文字が含まれていないことを確認できます。他の文字列を正規表現に置き換える場合は、次のようにできます/#{Regexp.escape(str)}/
Alex D

答えは、はい、しかしOPの質問ではありません。へのポインタをありがとうRegexp.escape()
David Moles

105

文字列の終わりの場合は、次のように使用することもできますchomp

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

式がa.chomp( "llo")の場合、chomp!より正確です。
フェルナンドゴンザレスサンチェス

1
副作用がないので、スライスよりきれいです!
Ardee Aram 2017

5
それは文字列の先頭からのものである場合、あなたも使用できるchompとの組み合わせでreverse"hello".reverse.chomp("he".reverse).reverse #=> "llo"
amoebe

45

ターゲット文字列が1つしかない場合は、次を使用できます。

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

1
私はそれを「楽しい」とは呼びません-おそらく直感的ではありません。
Jmoney38

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
そう、そうですね、bang-ifyingは、Rubyが既存の変数を変更する方法です。ありがとう@BennettTalpers
Dylan Pierce

26

Ruby 2.5以降

部分文字列が文字列の最初と最後にある場合、Ruby 2.5はこのためのメソッドを導入しています。

  • delete_prefix文字列の先頭から部分文字列を削除するための
  • 文字列の末尾から部分文字列を削除するためのdelete_suffix


1

私が正しく解釈している場合、この質問は文字列間のマイナス(-)演算、つまり組み込みのプラス(+)演算(連結)の反対のようなものを要求するようです。

以前の回答とは異なり、私はプロパティに従う必要があるような操作を定義しようとしています:

IF c = a + b THEN c-a = b AND c-b = a

これを実現するために必要な組み込みRubyメソッドは3つだけです。

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

一度に1つのメソッドを実行すると簡単に理解できるので、そのしくみについては説明しません。

以下が概念実証コードです。

# 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)を使用している場合の最後のアドバイスは、前の例のようにサルパッチング文字列の代わりに絞り込みを使用します。

それは次のように簡単です:

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

Öたとえば、OPは削除を要求しませんでした。
Iulian Onofrei 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.