例:
[12,23,987,43
最初の文字に[
aを使用して、「」を削除する最も速く効率的な方法は何chop()
ですか?
delete_prefix
\ delete_prefix!
)をベンチマークしましたが、かなり高速です。速度を上げるために以前のお気に入りを完全に無視するわけではありませんが、読みやすさはそれらが持つ素晴らしい新しいオプションであることを意味します!
例:
[12,23,987,43
最初の文字に[
aを使用して、「」を削除する最も速く効率的な方法は何chop()
ですか?
delete_prefix
\ delete_prefix!
)をベンチマークしましたが、かなり高速です。速度を上げるために以前のお気に入りを完全に無視するわけではありませんが、読みやすさはそれらが持つ素晴らしい新しいオプションであることを意味します!
回答:
私は次のようなものを使うのが好きです:
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つだけ実行して終了します。gsub
少なくとも2つのsub
呼び出しであると考えてください。
また、それはそれを覚えておくことが重要だgsub
、とsub
も部分文字列の検索よりもはるかにゆっくりと一致下手に書かれた正規表現によってハンディキャップをすることができます。可能であれば、正規表現をアンカーして、そこから最大の速度を得る。Stack Overflowには、それを実証する回答があります。詳細については、検索してください。
"[12,23,987,43".delete "["
what about "[12,23,987,43".shift ?
」?"[12,23,987,43".shift NoMethodError: undefined method
"[12,23,987,43":String`のシフト 'はどうですか?
上記のパブロの答えに似ていますが、日よけクリーナー:
str[1..-1]
1から最後の文字までの配列を返します。
'Hello World'[1..-1]
=> "ello World"
str[1,]
上記と比較してのパフォーマンスはどうですか?
str[1,]
範囲はなので、2番目の文字を返します1:nil
。str[1,999999]
テール全体を取得するには、実際に計算された長さ、または長さよりも長くなることが保証されているもの(たとえば、int_maxを使用)を提供する必要があります。[1..-1]
手動で長さを操作する必要がないので、(ベンチマークで[1..length]を参照)、より速く、おそらくクリーナーがあると
str[1..-2]
これを行うには、sliceを使用できます。
val = "abc"
=> "abc"
val.slice!(0)
=> "a"
val
=> "bc"
を使用slice!
すると、インデックスを指定して任意の文字を削除できます。
slice!(0)
使用asdf[0] = ''
するのはばかげている(正規表現でgsubを使用して榴弾砲でフライを撃つような)ので、このエレガントなものが本当に選択された答えになるはずです。
[]=
ませんが、slice!
追加の作業が必要な基礎となるCコードはそれほど必要ありません。合計します。議論は「どちらがより読みやすいですか?」かもしれません。私は[]=
可読性を使用しているのを見つけましたが、私はC-> Perlの背景から来ています。Java開発者はおそらくそれが読みにくいと思います。どちらも、タスクが簡単に理解でき、保守可能であり、CPUに過度の負荷がかからない限り、許容できる方法です。
Ruby 2.5以降では、delete_prefix
またはdelete_prefix!
を使用して、読み取り可能な方法でこれを実現できます。
この場合"[12,23,987,43".delete_prefix("[")
。
詳細はこちら:
'invisible'.delete_prefix('in') #=> "visible"
'pink'.delete_prefix('in') #=> "pink"
注意:これを使用してdelete_suffix
、およびで文字列の末尾からアイテムを削除することもできますdelete_suffix!
'worked'.delete_suffix('ed') #=> "work"
'medical'.delete_suffix('ed') #=> "medical"
編集:
Tin Manのベンチマークセットアップを使用すると、非常に高速に見えます(最後の2つのエントリdelete_p
との下delete_p!
)。非常に読みやすいですが、速度のために以前のお気に入りを完全にピップしません。
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)
私はこれが好きです:
str = "[12,23,987,43"
puts str[1..-1]
>> 12,23,987,43
常に先行括弧を取り除きたい場合:
"[12,23,987,43".gsub(/^\[/, "")
最初の文字を削除したいだけで、マルチバイト文字セットにならないことがわかっている場合:
"[12,23,987,43"[1..-1]
または
"[12,23,987,43".slice(1..-1)
"[12,23,987,43".sub(/^\[+/, "")
代わりに使用しますgsub(/^\[/, "")
。1つ目は、正規表現エンジンがすべての一致を検索できるようにし、1つのアクションで置き換えられ、Ruby 1.9.3と比べて速度が約2倍向上します。
gsub(/\A\[/, "")
どうでしょうか?
例: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つずつ削除できます。
簡単な方法:
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()
(注:簡単な方法をお勧めします:))
"[12,23,987,43".reverse.chop.reverse
ベンチマークをまとめてくれた@ 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
しかし、その迅速でありながら扱いにくいブラケット操作でできることは他にもあります。その間、完全を期すために、#shift
と#first
を書いてみましょう(なぜ配列にはすべての楽しみがあるべきですか?)引数を取り、最初から削除する文字数を指定します。
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
andと一貫したメソッドを使用して、文字列の先頭から文字Array#shift
を削除する明確な方法があります(これは本当にbangメソッドでなければなりませんか?)。そして、変更された文字列もで簡単に取得できます#eat!
。ええと、私たちは新しいeat!
ingパワーをアレイと共有すべきですか?何故なの!
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]
いいね!
chip()
代わりにchop()
(およびchimp()
のアナログとしてchomp()
)という名前のそのような関数について、Perlフォーラムで何年も前に議論したことを覚えています。
str = "[12,23,987,43"
str[0] = ""
list = [1,2,3,4] list.drop(1)
# => [2,3,4]
Listは、配列の先頭から1つ以上の要素を削除し、配列を変更せず、削除された要素の代わりに配列自体を返します。