1

私はハッシュ(数百のペア)を持っており、文字列を持っています。

この文字列で、ハッシュからのキーのすべての出現を、ハッシュからの値に応じて置き換えたいと思います。

私はこのようなことができることを理解しています

some_hash.each { |key, value| str = str.gsub(key, value) }

ただし、これを行うためのより良い(パフォーマンスの面で)方法があるかどうか疑問に思っています。

4

2 に答える 2

5

実行する必要があるのはgsub1回だけです。正規表現(鬼車)はCで実装されているため、Ruby内でループするよりも高速である必要があります。

some_hash = {
  "a" => "A",
  "b" => "B",
  "c" => "C",
}

"abcdefgabcdefg".gsub(Regexp.union(some_hash.keys), some_hash)
# => "ABCdefgABCdefg"
于 2013-01-08T18:47:29.423 に答える
2

いくつかのベンチマーク:

require 'benchmark'

SOME_HASH = Hash[('a'..'z').zip('A'..'Z')]
SOME_REGEX = Regexp.union(SOME_HASH.keys)

SHORT_STRING = ('a'..'z').to_a.join
LONG_STRING = SHORT_STRING * 100

N = 10_000

def sub1(str)
  SOME_HASH.each { |key, value|
    str = str.gsub(key, value) 
  } 
  str
end

def sub2(str)
  SOME_HASH.each { |key, value|
    str.gsub!(key, value) 
  } 
  str
end

def sub_regex(str)
  str.gsub(SOME_REGEX, SOME_HASH)
end

puts RUBY_VERSION
puts "#{ N } loops"
puts
puts "sub1: #{ sub1(SHORT_STRING) }"
puts "sub2: #{ sub2(SHORT_STRING) }"
puts "sub_regex: #{ sub_regex(SHORT_STRING) }"
puts

Benchmark.bm(10) do |b|

  b.report('gsub')  { N.times { sub1(LONG_STRING)      } }
  b.report('gsub!') { N.times { sub2(LONG_STRING)      } }
  b.report('regex') { N.times { sub_regex(LONG_STRING) } }

end

どの出力:

1.9.3
10000 loops

sub1: ABCDEFGHIJKLMNOPQRSTUVWXYZ
sub2: ABCDEFGHIJKLMNOPQRSTUVWXYZ
sub_regex: ABCDEFGHIJKLMNOPQRSTUVWXYZ

                user     system      total        real
gsub        14.360000   0.030000  14.390000 ( 14.412178)
gsub!        1.940000   0.010000   1.950000 (  1.957591)
regex        0.080000   0.000000   0.080000 (  0.075038)
于 2013-01-08T19:52:20.930 に答える