ruby: optimize => фраза.split (разделитель) .collect {| p | p.lstrip.rstrip} - PullRequest
4 голосов
/ 03 марта 2010

ruby: Какое выражение наиболее оптимизировано для того же результата, что и для

phrase.split(delimiter).collect {|p| p.lstrip.rstrip }

Ответы [ 3 ]

10 голосов
/ 03 марта 2010

Оптимизировано для ясности, я бы предпочел следующее:

phrase.split(delimiter).collect(&:strip)

Но я полагаю, вы хотите оптимизировать скорость. Я не знаю, почему другие спекулируют. Только способ выяснить, что быстрее, это сравнить ваш код.

Убедитесь, что вы настроили параметры эталонного теста - это только пример.

require "benchmark"

# Adjust parameters below for your typical use case.
n = 10_000
input = " This is - an example. - A relatively long string " +
  "- delimited by dashes. - Adjust if necessary " * 100
delimiter = "-"

Benchmark.bmbm do |bench|
  bench.report "collect { |s| s.lstrip.rstrip }" do
    # Your example.
    n.times { input.split(delimiter).collect { |s| s.lstrip.rstrip } }
  end

  bench.report "collect { |s| s.strip }" do
    # Use .strip instead of .lstrip.rstrip.
    n.times { input.split(delimiter).collect { |s| s.strip } }
  end

  bench.report "collect { |s| s.strip! }" do
    # Use .strip! to modifiy strings in-place.
    n.times { input.split(delimiter).collect { |s| s.strip! } }
  end

  bench.report "collect(&:strip!)" do
    # Slow block creation (&:strip! syntax).
    n.times { input.split(delimiter).collect(&:strip!) }
  end

  bench.report "split(/\\s*\#{delim}\\s*/) (static)" do
    # Use static regex -- only possible if delimiter doesn't change.
    re = Regexp.new("\s*#{delimiter}\s*")
    n.times { input.split(re) }
  end

  bench.report "split(/\\s*\#{delim}\\s*/) (dynamic)" do
    # Use dynamic regex, slower to create every time?
    n.times { input.split(Regexp.new("\s*#{delimiter}\s*")) }
  end
end

Результаты на моем ноутбуке с параметрами, указанными выше:

                                      user     system      total        real
collect { |s| s.lstrip.rstrip }   7.970000   0.050000   8.020000 (  8.246598)
collect { |s| s.strip }           6.350000   0.050000   6.400000 (  6.837892)
collect { |s| s.strip! }          5.110000   0.020000   5.130000 (  5.148050)
collect(&:strip!)                 5.700000   0.030000   5.730000 (  6.010845)
split(/\s*#{delim}\s*/) (static)  6.890000   0.030000   6.920000 (  7.071058)
split(/\s*#{delim}\s*/) (dynamic) 6.900000   0.020000   6.920000 (  6.983142)

Из вышесказанного я могу сделать вывод:

  • Использование strip вместо .lstrip.rstrip быстрее.
  • Предпочтение &:strip! над { |s| s.strip! } сопряжено с затратами на производительность.
  • Простые шаблоны регулярных выражений почти такие же быстрые, как и split + strip.

Вещи, которые я могу придумать, могут повлиять на результат:

  • Длина разделителя (и является ли он пробелом).
  • Длина строк, которые вы хотите разделить.
  • Длина разделяемых кусков в строке.

Но не верьте мне на слово. Мера!

1 голос
/ 03 марта 2010

Вы можете попробовать регулярное выражение:

phrase.strip.split(/\s*#{delimiter}\s*/)
0 голосов
/ 03 марта 2010

Я вижу только оптимизацию в пропуске

p.lstrip.rstrip

с

p.strip!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...