Проверьте, есть ли строковая переменная в наборе строк - PullRequest
6 голосов
/ 12 марта 2011

Какой из них лучше:

x == 'abc' || x == 'def' || x == 'ghi'
%w(abc def ghi).include? x
x =~ /abc|def|ghi/

?

Ответы [ 3 ]

7 голосов
/ 12 марта 2011

Какой из них лучше? На этот вопрос нелегко ответить, потому что они не все делают одно и то же.

x == 'abc' || x == 'def' || x == 'ghi'
%w(abc def ghi).include? x

сравнить x с фиксированными строками на равенство. x должно быть одним из этих значений. Между этими двумя я склоняюсь ко второму, потому что его легче поддерживать. Представьте, как бы это выглядело, если бы вам пришлось сравнивать двадцать, пятьдесят или сто строк.

Третий тест:

x ~= /abc|def|ghi/

соответствует подстроке:

x = 'xyzghi'
(x =~ /abc|def|ghi/) # => 3

так что это не то же самое, что первые два.

РЕДАКТИРОВАТЬ: Есть некоторые вещи в тестах, сделанные Nash, что я бы сделал по-другому. Используя Ruby 1.9.2-p180 на MacBook Pro, он проверяет 1 000 000 циклов и сравнивает результаты привязки регулярного выражения, используя группировку и не разделяя массив %w() каждый раз по циклу:

require 'benchmark'
str = "test"

n = 1_000_000
Benchmark.bm do |x|
  x.report { n.times { str == 'abc' || str == 'def' || str == 'ghi' } }
  x.report { n.times { %w(abc def ghi).include? str } }
  x.report { ary = %w(abc def ghi); n.times { ary.include? str } }
  x.report { n.times { str =~ /abc|def|ghi/ } }
  x.report { n.times { str =~ /^abc|def|ghi$/ } }
  x.report { n.times { str =~ /^(abc|def|ghi)$/ } }
  x.report { n.times { str =~ /^(?:abc|def|ghi)$/ } }
  x.report { n.times { str =~ /\b(?:abc|def|ghi)\b/ } }
end
# >>       user     system      total        real
# >>   1.160000   0.000000   1.160000 (  1.165331)
# >>   1.920000   0.000000   1.920000 (  1.920120)
# >>   0.990000   0.000000   0.990000 (  0.983921)
# >>   1.070000   0.000000   1.070000 (  1.068140)
# >>   1.050000   0.010000   1.060000 (  1.054852)
# >>   1.060000   0.000000   1.060000 (  1.063909)
# >>   1.060000   0.000000   1.060000 (  1.050813)
# >>   1.050000   0.000000   1.050000 (  1.056147)
2 голосов
/ 12 марта 2011

некоторые тесты:

require 'benchmark'
str = "test"
Benchmark.bm do |x|
  x.report {100000.times {if str == 'abc' || str == 'def' || str == 'ghi'; end}}
  x.report {100000.times {if %w(abc def ghi).include? str; end}}
  x.report {100000.times {if str =~ /abc|def|ghi/; end}}
end

    user     system      total        real
0.250000   0.000000   0.250000 (  0.251014)
0.374000   0.000000   0.374000 (  0.402023)
0.265000   0.000000   0.265000 (  0.259014)

Так что, как видите, первый способ работает быстрее, чем другой.И чем длиннее str, тем медленнее работает последний способ:

str = "testasdasdasdasdasddkmfskjndfbdkjngdjgndksnfg"
    user     system      total        real
0.234000   0.000000   0.234000 (  0.248014)
0.405000   0.000000   0.405000 (  0.403023)
1.046000   0.000000   1.046000 (  1.038059)
2 голосов
/ 12 марта 2011

Первый может быть немного быстрее, поскольку нет вызовов методов и вы выполняете прямое сравнение строк, но он также, вероятно, наименее читаемый и наименее обслуживаемый.

Второй, безусловно, самый крутой и рубиновый. Это наиболее удобный и, вероятно, лучший для чтения.

Последний способ использует синтаксис регулярного выражения старой школы Perl. Довольно быстрый, не такой раздражающий, как первый в обслуживании, довольно читабельный.

Полагаю, это зависит от того, что вы подразумеваете под "лучше".

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