web-dev-qa-db-ja.com

Ruby、文字列から最後のN文字を削除する

文字列から最後のn文字を削除するための好ましい方法は何ですか?

235
JP Silvashy

削除したい文字が常に同じ文字である場合は、chompを検討してください。

'abc123'.chomp('123')    # => "abc"

chompの利点は次のとおりです。カウントが不要で、コードが実行していることをより明確に伝えます。

引数を指定しないと、chompはDOSまたはUnixの行末を削除します(どちらかが存在する場合)。

"abc\n".chomp      # => "abc"
"abc\r\n".chomp    # => "abc"

コメントから、#chompを使用することと範囲を使用することの速度の問題がありました。ここでは両者を比較するベンチマークです:

require 'benchmark'

S = 'asdfghjkl'
SL = S.length
T = 10_000
A = 1_000.times.map { |n| "#{n}#{S}" }

GC.disable

Benchmark.bmbm do |x|
  x.report('chomp') { T.times { A.each { |s| s.chomp(S) } } }
  x.report('range') { T.times { A.each { |s| s[0...-SL] } } }
end

ベンチマーク結果(CRuby 2.13p242を使用):

Rehearsal -----------------------------------------
chomp   1.540000   0.040000   1.580000 (  1.587908)
range   1.810000   0.200000   2.010000 (  2.011846)
-------------------------------- total: 3.590000sec

            user     system      total        real
chomp   1.550000   0.070000   1.620000 (  1.610362)
range   1.970000   0.170000   2.140000 (  2.146682)

そのため、chompは範囲を使用するよりも最大22%高速です。

259
Wayne Conrad
irb> 'now is the time'[0...-4]
=> "now is the "
300
DigitalRoss
str = str[0...-n]
52
Nakilon
name = "my text"
x.times do name.chop! end

これがコンソールです。

>name = "Nabucodonosor"
 => "Nabucodonosor" 
> 7.times do name.chop! end
 => 7 
> name
 => "Nabuco" 
29
joscas

私はchopname__を提案するでしょう。私はそれがコメントの1つで言及されていると思いますが、リンクや説明はありません。

これは単に文字列から最後の文字を削除するだけで、そのために値を指定する必要はありません。

複数の文字を削除する必要がある場合はchompname__が最善の策です。これが Rubyドキュメントchopname__について言えることです。

最後の文字を削除した新しい文字列を返します。文字列が\ r\nで終わる場合は、両方の文字が削除されます。空の文字列にchopを適用すると、空の文字列が返されます。 String#chompは、レコード区切り文字で終わらない場合は文字列を変更しないため、多くの場合より安全な代替方法です。

これは主に\r\nなどの区切り文字を削除するために使用されますが、単純な文字列から最後の文字を削除するために使用されます。たとえば、Wordを単数にするためのsname__です。

28
kakubei

最後のn文字を削除することは、最初のlength - n文字をそのままにすることと同じです。

アクティブサポートは String#firstString#last のメソッドを含み、これらは最初/最後のn文字を保持または削除する便利な方法を提供します。

require 'active_support/core_ext/string/access'

"foobarbaz".first(3)  # => "foo"
"foobarbaz".first(-3) # => "foobar"
"foobarbaz".last(3)   # => "baz"
"foobarbaz".last(-3)  # => "barbaz"
13
chocolateboy

Ruby 2.5+

Ruby 2.5の時点で、delete_suffixまたはdelete_suffix!を使用して、高速で読みやすい方法でこれを実現できます。

メソッドのドキュメントは here です。

あなたが接尾辞が何であるかを知っているなら、これは慣用的です(そして、私はここで他の答えよりもさらに読みやすいと主張します):

'abc123'.delete_suffix('123')     # => "abc"
'abc123'.delete_suffix!('123')    # => "abc"

一番上の回答よりもはるかに高速です(bangメソッドではほぼ40%)。同じベンチマークの結果は次のとおりです。

                     user     system      total        real
chomp            0.949823   0.001025   0.950848 (  0.951941)
range            1.874237   0.001472   1.875709 (  1.876820)
delete_suffix    0.721699   0.000945   0.722644 (  0.723410)
delete_suffix!   0.650042   0.000714   0.650756 (  0.651332)

これが便利であることを願っています-メソッドは現在正規表現を受け入れないので、サフィックスがわからない場合は当面は実行できないことに注意してください。しかし、受け入れられた答え(update:執筆時)は同じことを指示しているので、これは一部の人々にとって有用だと思いました。

8
SRack

railsを使っているのなら、試してみてください。

"my_string".last(2) # => "ng"

[編集済み]

最後の2文字なしで文字列を取得するには

n = "my_string".size
"my_string"[0..n-3] # => "my_stri"

注:最後の文字列charはn-1です。したがって、最後の2を削除するには、n-3を使用します。

7
Guihen

あなたはいつものようなものを使うことができます

 "string".sub!(/.{X}$/,'')

Xは削除する文字数です。

あるいは結果を代入/使用して:

myvar = "string"[0..-X]

Xは、削除する文字数プラス1です。

3
Zsolt Botykai

slice()メソッドをチェックしてください。

http://Ruby-doc.org/core-2.5.0/String.html#method-i-slice

3
Cody Caughlan

クラスメソッドの作成に問題がなく、切り取った文字が欲しい場合は、次の手順を試してください。

class String
  def chop_multiple(amount)
    amount.times.inject([self, '']){ |(s, r)| [s.chop, r.prepend(s[-1])] }
  end
end

hello, world = "hello world".chop_multiple 5
hello #=> 'hello '
world #=> 'world'
1
Ben Aubin

正規表現を使う:

str = 'string'
n = 2  #to remove last n characters

str[/\A.{#{str.size-n}}/] #=> "stri"
0
Sagar Pandya