我已经返回一个三元运算符来检索和索引,如下所示
val = (
(@str_value.index("APPLE")).nil ? (
(@str_value.index("DIAMOND")).nil ? @str_value.index("GARLIC") : str_value.index("DIAMOND")
) : @str_value.index("APPLE")
)
但是当我运行它时它会给我一个错误。
undefined method `nil' for nil:NilClass
我是Ruby的新手。什么可能出错?
答案 0 :(得分:7)
基准时间:
require 'benchmark'
def amit_kumar_gupta(str_value)
str_value.index("APPLE") || str_value.index("DIAMOND") || str_value.index("GARLIC")
end
def priti(str_value)
%w(APPLE DIAMOND GARLIC).map{|i| str_value.index(i)}.compact[0]
end
def borodin(str_value)
/APPLE|DIAMOND|GARLIC/ =~ str_value
end
# I added a single anchor, based on knowledge of where the target would be, to
# show the difference an anchored search can make.
def borodin2(str_value)
str_value[/\b (?:APPLE|DIAMOND|GARLIC) \b\Z/x]
end
STRING = ('a'..'z').to_a.join * 100
APPLE_STRING = STRING + ' APPLE'
GARLIC_STRING = STRING + ' GARLIC'
N = 100_000
puts "RUBY_VERSION = #{ RUBY_VERSION }"
puts "N = #{N}"
Benchmark.bm(15) do |b|
b.report('amit apple') { N.times { amit_kumar_gupta(APPLE_STRING) } }
b.report('amit garlic') { N.times { amit_kumar_gupta(GARLIC_STRING) } }
b.report('priti apple') { N.times { priti(APPLE_STRING) } }
b.report('priti garlic') { N.times { priti(GARLIC_STRING) } }
b.report('borodin apple') { N.times { borodin(APPLE_STRING) } }
b.report('borodin garlic') { N.times { borodin(GARLIC_STRING) } }
b.report('borodin2 apple') { N.times { borodin2(APPLE_STRING) } }
b.report('borodin2 garlic') { N.times { borodin2(GARLIC_STRING) } }
end
结果为1.9.3:
RUBY_VERSION = 1.9.3
N = 100000
user system total real
amit apple 0.540000 0.000000 0.540000 ( 0.539550)
amit garlic 1.560000 0.000000 1.560000 ( 1.567501)
priti apple 1.670000 0.000000 1.670000 ( 1.673736)
priti garlic 1.630000 0.000000 1.630000 ( 1.630529)
borodin apple 0.810000 0.010000 0.820000 ( 0.811853)
borodin garlic 0.810000 0.000000 0.810000 ( 0.817202)
borodin2 apple 0.220000 0.000000 0.220000 ( 0.223292)
borodin2 garlic 0.230000 0.000000 0.230000 ( 0.225041)
和Ruby 2.0.0-p195:
RUBY_VERSION = 2.0.0
N = 100000
user system total real
amit apple 0.250000 0.000000 0.250000 ( 0.253446)
amit garlic 0.730000 0.000000 0.730000 ( 0.730139)
priti apple 0.820000 0.000000 0.820000 ( 0.825674)
priti garlic 0.820000 0.010000 0.830000 ( 0.821391)
borodin apple 2.230000 0.000000 2.230000 ( 2.240345)
borodin garlic 2.250000 0.010000 2.260000 ( 2.264021)
borodin2 apple 0.200000 0.000000 0.200000 ( 0.197568)
borodin2 garlic 0.190000 0.000000 0.190000 ( 0.197615)
我们学到了什么(多萝西)?:
Amit的代码利用||
短路测试。如果index("APPLE")
找到该值,则不需要进一步测试并停止处理。对于大型工作来说,这是一个巨大的时间和CPU节省。您可以看到必须搜索“APPLE”与“GARLIC”之间差异的效果。第一次在一次测试后返回,第二次在三次测试后返回。
Priti's正在强制进行所有测试,无论第一个或第二个是否找到答案,然后丢弃失败的结果。这是一种天真的尝试,而不是如何编写这种代码。
Borodin的代码展示了如何简洁地测试一大堆不同的字符串,但正则表达式有很多开销可以减慢它们的速度。有趣的是,v2.0-p195比1.9.3慢得多。我不知道这是一个错误还是什么,但它很重要。在borodin2
代码中,我还展示了如何捕获完整的单词,而不仅仅是子字符串。这在进行文本处理时非常重要,并且当您不使用正则表达式时变得更加困难。如果你完整的话,那么正则表达式是我认为的唯一方法。
我添加了borodin2
测试并添加了一个“行尾”锚点,以显示关于字符串结构的一点点知识的重要性。使用rindex
代替index
也可以改善前四个测试,并且在所有情况下,如果目标字符串位于搜索字符串的前面,它们就会降级。这种先验知识很重要。扫描您的数据并了解您正在寻找的内容,如果您能找到可以利用的模式,那么您的代码可以更快地运行。
在我看来,由于短路,Amit的代码是最好的通用代码。 Borodin的代码是最容易扩展的代码,并且在1.9.3时速度更快,但2.0版本正在受到影响。就个人而言,我会假设他们会弄清楚在另一轮Ruby中减慢速度,而不是YMMV。borodin
或borodin2
。在我的机器上2.0.0-p195和2.0.0-p247之间几乎没有区别,所以我没有显示其结果。并且,也许这是我的模式中的一个缺陷,其中一个非常聪明的Ruby人员会想要纠正它。
修改代码以使用Fruity:
require 'fruity'
def amit_kumar_gupta(str_value)
str_value.index("APPLE") || str_value.index("DIAMOND") || str_value.index("GARLIC")
end
def priti(str_value)
%w(APPLE DIAMOND GARLIC).map{|i| str_value.index(i)}.compact[0]
end
def borodin(str_value)
/APPLE|DIAMOND|GARLIC/ =~ str_value
end
# I added a single anchor, based on knowledge of where the target would be, to
# show the difference an anchored search can make.
def borodin2(str_value)
str_value[/\b (?:APPLE|DIAMOND|GARLIC) \b\Z/x]
end
STRING = ('a'..'z').to_a.join * 100
APPLE_STRING = STRING + ' APPLE'
GARLIC_STRING = STRING + ' GARLIC'
puts "RUBY_VERSION = #{ RUBY_VERSION }"
compare do
amit_apple { amit_kumar_gupta(APPLE_STRING) }
amit_garlic { amit_kumar_gupta(GARLIC_STRING) }
priti_apple { priti(APPLE_STRING) }
priti_garlic { priti(GARLIC_STRING) }
borodin_apple { borodin(APPLE_STRING) }
borodin_garlic { borodin(GARLIC_STRING) }
borodin2_apple { borodin2(APPLE_STRING) }
borodin2_garlic { borodin2(GARLIC_STRING) }
end
RUBY_VERSION = 2.1.0
Running each test 4096 times. Test will take about 6 seconds.
amit_apple is faster than amit_garlic by 2.6x ± 0.1
amit_garlic is faster than borodin2_garlic by 10.000000000000009% ± 1.0% (results differ: 2601 vs GARLIC)
borodin2_garlic is similar to borodin2_apple (results differ: GARLIC vs APPLE)
borodin2_apple is faster than priti_apple by 39.99999999999999% ± 1.0% (results differ: APPLE vs 2601)
priti_apple is similar to priti_garlic
priti_garlic is faster than borodin_apple by 10x ± 0.1
borodin_apple is faster than borodin_garlic by 2.0000000000000018% ± 1.0%
返回:
RUBY_VERSION = 2.1.0 Running each test 4096 times. Test will take about 6 seconds. amit_apple is faster than amit_garlic by 2.6x ± 0.1 amit_garlic is faster than borodin2_garlic by 10.000000000000009% ± 1.0% (results differ: 2601 vs GARLIC) borodin2_garlic is similar to borodin2_apple (results differ: GARLIC vs APPLE) borodin2_apple is faster than priti_apple by 39.99999999999999% ± 1.0% (results differ: APPLE vs 2601) priti_apple is similar to priti_garlic priti_garlic is faster than borodin_apple by 10x ± 0.1 borodin_apple is faster than borodin_garlic by 2.0000000000000018% ± 1.0%
答案 1 :(得分:4)
@str_value.index("APPLE") || @str_value.index("DIAMOND") || @str_value.index("GARLIC")
答案 2 :(得分:3)
简单地
val = /APPLE|DIAMOND|GARLIC/ =~ @str_value
答案 3 :(得分:2)
返回str中给定子字符串或模式(regexp)第一次出现的索引。 如果找不到,则返回nil 。如果存在第二个参数,则它指定字符串中开始搜索的位置。
改为使用@str_value.index("APPLE")).nil? ?
。
您错过了一个?
@str_value.index("APPLE")).nil ?
请注意nil
对象有nil?
方法而非nil
方法:
nil.methods.grep(/nil/)
# => [nil?]
所以表达式的修复是:
@str_value = "I love APPLE"
val = @str_value.index("APPLE") ? (@str_value.index("DIAMOND") ? @str_value.index("GARLIC") : @str_value.index("DIAMOND")) : @str_value.index("APPLE")
p val # => nil
更好的是:
@str_value = "I love APPLE"
%w(APPLE DIAMOND GARLIC).map{|i| @str_value.index(i)}.compact[0]
#>> 7