web-dev-qa-db-ja.com

文字列から最初の文字を削除する最も簡単な方法は何ですか?

例:

[12,23,987,43

[」を削除する最も高速で効率的な方法は、おそらくchop()を使用しますが、最初の文字は何ですか?

162
NullVoxPopuli

私は次のようなものを使うのが好きです:

 asdf = "[12,23,987,43" 
 asdf [0] = '' 
 
 p asdf 
#>> "12、 23,987,43 "

私は常に最速で最も読みやすい方法を探しています:

require 'benchmark'

N = 1_000_000

puts Ruby_VERSION

STR = "[12,23,987,43"

Benchmark.bm(7) do |b|
  b.report('[0]') { N.times { "[12,23,987,43"[0] = '' } }
  b.report('sub') { N.times { "[12,23,987,43".sub(/^\[+/, "") } }

  b.report('gsub') { N.times { "[12,23,987,43".gsub(/^\[/, "") } }
  b.report('[1..-1]') { N.times { "[12,23,987,43"[1..-1] } }
  b.report('slice') { N.times { "[12,23,987,43".slice!(0) } }
  b.report('length') { N.times { "[12,23,987,43"[1..STR.length] } }

end

Mac Proで実行する:

1.9.3
              user     system      total        real
[0]       0.840000   0.000000   0.840000 (  0.847496)
sub       1.960000   0.010000   1.970000 (  1.962767)
gsub      4.350000   0.020000   4.370000 (  4.372801)
[1..-1]   0.710000   0.000000   0.710000 (  0.713366)
slice     1.020000   0.000000   1.020000 (  1.020336)
length    1.160000   0.000000   1.160000 (  1.157882)

もう1つの提案された回答を組み込むための更新:

require 'benchmark'

N = 1_000_000

class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end

  def first(how_many = 1)
    self[0...how_many]
  end

  def shift(how_many = 1)
    shifted = first(how_many)
    self.replace self[how_many..-1]
    shifted
  end
  alias_method :shift!, :shift
end

class Array
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

puts Ruby_VERSION

STR = "[12,23,987,43"

Benchmark.bm(7) do |b|
  b.report('[0]') { N.times { "[12,23,987,43"[0] = '' } }
  b.report('sub') { N.times { "[12,23,987,43".sub(/^\[+/, "") } }

  b.report('gsub') { N.times { "[12,23,987,43".gsub(/^\[/, "") } }
  b.report('[1..-1]') { N.times { "[12,23,987,43"[1..-1] } }
  b.report('slice') { N.times { "[12,23,987,43".slice!(0) } }
  b.report('length') { N.times { "[12,23,987,43"[1..STR.length] } }
  b.report('eat!') { N.times { "[12,23,987,43".eat! } }
  b.report('reverse') { N.times { "[12,23,987,43".reverse.chop.reverse } }
end

結果:

2.1.2
              user     system      total        real
[0]       0.300000   0.000000   0.300000 (  0.295054)
sub       0.630000   0.000000   0.630000 (  0.631870)
gsub      2.090000   0.000000   2.090000 (  2.094368)
[1..-1]   0.230000   0.010000   0.240000 (  0.232846)
slice     0.320000   0.000000   0.320000 (  0.320714)
length    0.340000   0.000000   0.340000 (  0.341918)
eat!      0.460000   0.000000   0.460000 (  0.452724)
reverse   0.400000   0.000000   0.400000 (  0.399465)

そして、別の/^./を使用して最初の文字を見つけます:

require 'benchmark'

N = 1_000_000

class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end

  def first(how_many = 1)
    self[0...how_many]
  end

  def shift(how_many = 1)
    shifted = first(how_many)
    self.replace self[how_many..-1]
    shifted
  end
  alias_method :shift!, :shift
end

class Array
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

puts Ruby_VERSION

STR = "[12,23,987,43"

Benchmark.bm(7) do |b|
  b.report('[0]') { N.times { "[12,23,987,43"[0] = '' } }
  b.report('[/^./]') { N.times { "[12,23,987,43"[/^./] = '' } }
  b.report('[/^\[/]') { N.times { "[12,23,987,43"[/^\[/] = '' } }
  b.report('sub+') { N.times { "[12,23,987,43".sub(/^\[+/, "") } }
  b.report('sub') { N.times { "[12,23,987,43".sub(/^\[/, "") } }
  b.report('gsub') { N.times { "[12,23,987,43".gsub(/^\[/, "") } }
  b.report('[1..-1]') { N.times { "[12,23,987,43"[1..-1] } }
  b.report('slice') { N.times { "[12,23,987,43".slice!(0) } }
  b.report('length') { N.times { "[12,23,987,43"[1..STR.length] } }
  b.report('eat!') { N.times { "[12,23,987,43".eat! } }
  b.report('reverse') { N.times { "[12,23,987,43".reverse.chop.reverse } }
end

結果:

# >> 2.1.5
# >>               user     system      total        real
# >> [0]       0.270000   0.000000   0.270000 (  0.270165)
# >> [/^./]    0.430000   0.000000   0.430000 (  0.432417)
# >> [/^\[/]   0.460000   0.000000   0.460000 (  0.458221)
# >> sub+      0.590000   0.000000   0.590000 (  0.590284)
# >> sub       0.590000   0.000000   0.590000 (  0.596366)
# >> gsub      1.880000   0.010000   1.890000 (  1.885892)
# >> [1..-1]   0.230000   0.000000   0.230000 (  0.223045)
# >> slice     0.300000   0.000000   0.300000 (  0.299175)
# >> length    0.320000   0.000000   0.320000 (  0.325841)
# >> eat!      0.410000   0.000000   0.410000 (  0.409306)
# >> reverse   0.390000   0.000000   0.390000 (  0.393044)

より高速なハードウェアとRubyの新しいバージョンに関する別のアップデートを次に示します。

2.3.1
              user     system      total        real
[0]       0.200000   0.000000   0.200000 (  0.204307)
[/^./]    0.390000   0.000000   0.390000 (  0.387527)
[/^\[/]   0.360000   0.000000   0.360000 (  0.360400)
sub+      0.490000   0.000000   0.490000 (  0.492083)
sub       0.480000   0.000000   0.480000 (  0.487862)
gsub      1.990000   0.000000   1.990000 (  1.988716)
[1..-1]   0.180000   0.000000   0.180000 (  0.181673)
slice     0.260000   0.000000   0.260000 (  0.266371)
length    0.270000   0.000000   0.270000 (  0.267651)
eat!      0.400000   0.010000   0.410000 (  0.398093)
reverse   0.340000   0.000000   0.340000 (  0.344077)

なぜgsubがそんなに遅いのですか?

検索/置換を行った後、gsubは、終了したかどうかを判断する前に、可能な追加の一致をチェックする必要があります。 subは1つだけを実行して終了します。少なくとも2つのgsub呼び出しであるように、subを考慮してください。

また、gsubおよびsubは、部分文字列検索よりもはるかにゆっくりと一致する、不完全に記述された正規表現によっても障害を受ける可能性があることを覚えておくことが重要です。可能であれば、正規表現を固定して、速度を最大化します。ここでStack Overflowに回答がありますので、詳細が必要な場合は検索してください。

217
the Tin Man

上記のパブロの答えに似ていますが、シェードクリーナー:

str[1..-1]

1から最後の文字までの配列を返します。

'Hello World'[1..-1]
 => "Ello World"
274
Jason Stirk

これを行うためにスライスを使用できます:

val = "abc"
 => "abc" 
val.slice!(0)
 => "a" 
val
 => "bc" 

slice!を使用して、インデックスを指定することで任意の文字を削除できます。

48
balanv

私はこれが好きです:

str = "[12,23,987,43"
puts str[1..-1]
>> 12,23,987,43
15
henriquesuda

常に先頭のブラケットを削除する場合:

"[12,23,987,43".gsub(/^\[/, "")

最初の文字を削除したいだけで、マルチバイト文字セットに含まれないことがわかっている場合:

"[12,23,987,43"[1..-1]

または

"[12,23,987,43".slice(1..-1)
14
Chris Heald

Ruby 2.5+

Ruby 2.5以降では、delete_prefixまたはdelete_prefix!を使用して、読みやすい方法でこれを実現できます。

この場合、"[12,23,987,43".delete_prefix("[")

詳細はこちら:

https://blog.jetbrains.com/Ruby/2017/10/10-new-features-in-Ruby-2-5/

https://bugs.Ruby-lang.org/issues/12694

'invisible'.delete_prefix('in') #=> "visible"
'pink'.delete_prefix('in') #=> "pink"

N.B.これを使用して、delete_suffixおよびdelete_suffix!を使用して文字列の末尾から項目を削除することもできます

'worked'.delete_suffix('ed') #=> "work"
'medical'.delete_suffix('ed') #=> "medical"

https://bugs.Ruby-lang.org/issues/13665

編集:

Tin Manのベンチマークセットアップを使用すると、非常に高速に見えます(最後の2つのエントリdelete_pおよびdelete_p!の下)。非常に読みやすいですが、quiteスピードのために以前のお気に入りをピップしません。

2.5.0
              user     system      total        real
[0]       0.174766   0.000489   0.175255 (  0.180207)
[/^./]    0.318038   0.000510   0.318548 (  0.323679)
[/^\[/]   0.372645   0.001134   0.373779 (  0.379029)
sub+      0.460295   0.001510   0.461805 (  0.467279)
sub       0.498351   0.001534   0.499885 (  0.505729)
gsub      1.669837   0.005141   1.674978 (  1.682853)
[1..-1]   0.199840   0.000976   0.200816 (  0.205889)
slice     0.279661   0.000859   0.280520 (  0.285661)
length    0.268362   0.000310   0.268672 (  0.273829)
eat!      0.341715   0.000524   0.342239 (  0.347097)
reverse   0.335301   0.000588   0.335889 (  0.340965)
delete_p  0.222297   0.000832   0.223129 (  0.228455)
delete_p!  0.225798   0.000747   0.226545 (  0.231745)
9
SRack

非効率的な代替手段:

str.reverse.chop.reverse
6
jaamun

例:a = "One Two Three"

1.9.2-p290 > a = "One Two Three"
 => "One Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "ne Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "e Two Three" 

1.9.2-p290 > a = a[1..-1]
 => " Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "wo Three" 

この方法で、文字列の最初の文字を1つずつ削除できます。

4
Rubyist

ベンチマークをまとめてくれた@ the-tin-manに感謝します!

残念ながら、私はこれらのソリューションのどれも本当に好きではありません。結果を取得するために追加の手順が必要([0] = ''.strip!)か、何が起こっているのかについてあまり意味的/明確でない([1..-1]:「あ、1から負の1の範囲?Yearg?」)、または遅いまたは書き出すのに時間がかかる(.gsub.length)。

私たちが試みているのは「シフト」(配列用語)ですが、シフトされたものではなく、残りの文字を返します。 Rubyを使用して、文字列でこれを可能にしましょう。スピーディなブラケット操作を使用できますが、適切な名前を付けて、引数を取り、前面からどれだけ削りたいかを指定します。

class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

しかし、この高速で扱いにくいブラケット操作では、さらに多くのことができます。完全を期すために、Stringに#shift#firstを書きましょう(なぜArrayにすべての楽しみが必要なのでしょうか?)、最初から削除したい文字数を指定する引数を取ります:

class String
  def first(how_many = 1)
    self[0...how_many]
  end

  def shift(how_many = 1)
    shifted = first(how_many)
    self.replace self[how_many..-1]
    shifted
  end
  alias_method :shift!, :shift
end

わかりました。これで、Array#firstおよびArray#shiftと一致するメソッドを使用して、文字列の先頭から文字を引き出す明確な方法ができました(実際にはbangメソッドですか??)。また、#eat!を使用して、変更した文字列も簡単に取得できます。うーん、新しいeat!ingパワーをArrayと共有すべきですか?何故なの!

class Array
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

できるようになりました:

> str = "[12,23,987,43" #=> "[12,23,987,43"
> str.eat!              #=> "12,23,987,43"
> str                   #=> "12,23,987,43"

> str.eat!(3)           #=> "23,987,43"
> str                   #=> "23,987,43"

> str.first(2)          #=> "23"
> str                   #=> "23,987,43"

> str.shift!(3)         #=> "23,"
> str                   #=> "987,43"

> arr = [1,2,3,4,5]     #=> [1, 2, 3, 4, 5] 
> arr.eat!              #=> [2, 3, 4, 5] 
> arr                   #=> [2, 3, 4, 5] 

それは良いです!

3
brookr

簡単な方法:

str = "[12,23,987,43"

removed = str[1..str.length]

素晴らしい方法:

class String
  def reverse_chop()
    self[1..self.length]
  end
end

"[12,23,987,43".reverse_chop()

(注:簡単な方法をお勧めします:))

3
Pablo Fernandez
str = "[12,23,987,43"

str[0] = ""
2
Handcraftsman

list = [1,2,3,4] list.drop(1)

# => [2,3,4]

Listは、配列の先頭から1つ以上の要素を削除し、配列を変更せず、削除された要素の代わりに配列自体を返します。

0
Aaron Henderson
class String
  def bye_felicia()
    felicia = self.strip[0] #first char, not first space.
    self.sub(felicia, '')
  end
end
0
Josh Brody

正規表現を使用する:

str = 'string'
n = 1  #to remove first n characters

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

読みやすさのために、str.delete(str[0])であるニースのソリューションを見つけましたが、そのパフォーマンスを証明することはできません。

0
zeitchef