带零的三元运算符。如何在Ruby中使用

带零的三元运算符。如何在Ruby中使用,ruby,Ruby,我返回了一个三元运算符来检索和索引,如下所示 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:N

我返回了一个三元运算符来检索和索引,如下所示

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不熟悉。可能出现什么问题?

返回str中给定子字符串或模式(regexp)第一次出现的索引。如果未找到,则返回nil。如果存在第二个参数,则它指定字符串中开始搜索的位置

使用
@str_value.index(“苹果”).nil取而代之

您在这里错过了一个
@str\u value.index(“苹果”)。无?

查看
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
简单地

基准时间:

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的代码利用了
|
短路测试。如果
索引(“苹果”)
发现该值,则无需进一步测试,处理停止。对于大型作业来说,这是一个巨大的时间和CPU节省。你可以从搜索“苹果”和“大蒜”的区别中看到效果。第一个在一次测试后返回,第二个在三次测试后返回

Priti’s正在强制所有测试,不管第一个或第二个是否找到答案,然后扔掉失败的结果。这是一个天真的尝试,而不是如何编写这种代码

Borodin的代码显示了如何简洁地测试一大堆不同的字符串,但是正则表达式有很多开销,这会降低它们的速度。有趣的是,v2.0-p195比1.9.3慢得多。我不知道这是一个bug还是什么,但它很重要。在
borodin2
代码中,我还演示了如何捕获完整的单词,而不仅仅是子字符串。这在进行文本处理时非常重要,在不使用正则表达式时,这将变得非常困难。如果你想要完整的单词,那么在我看来正则表达式是唯一的选择

我添加了
borodin2
测试,并添加了一个“线端”锚,以显示关于字符串结构的一点点知识是多么重要。使用
rindex
而不是
index
也会改进前四个测试,而且在所有情况下,如果目标字符串位于搜索字符串的前面,那么它们都会降级。预先了解是很重要的。扫描你的数据,了解你在寻找什么,如果你能找到可以利用的模式,那么你的代码可以运行得更快

在我看来,阿米特的代码是最好的通用代码,因为短路。Borodin的代码是最容易扩展的,在1.9.3版本中速度更快,但在2.0版本中却很困难。就我个人而言,我会使用
borodin
borodin2
,前提是他们会在另一版本的Ruby中找出是什么让它慢下来的,但是YMMV。在我的机器上,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% RUBY_版本=2.1.0 运行每个测试4096次。测试大约需要6秒钟。 amit_苹果比amit_大蒜快2.6倍±0.1倍 amit_大蒜比borodin2_大蒜快10.00000000000000 9%±1.0%(结果不同:2601与大蒜) borodin2_大蒜与borodin2_苹果相似(结果不同:大蒜与苹果) borodin2_苹果比priti_苹果快39.99999999999%±1.0%(结果不同:苹果与2601) priti_苹果与priti_大蒜相似 priti_大蒜比Borodinu苹果快10倍±0.1 borodin_苹果比borodin_大蒜快2.00000000000000 18%±1.0%

你想要的方法名为
nil?
。请给出几个例子
@str_value
/
expected_val
,这个代码段很糟糕,毫无疑问有更好的方法来编写它。如果你没有internet访问权,将来要解决与此相关的问题,
nil.methods.select{m | m.match/nil/}
应该提供您想要的确切方法,甚至是零。从irb或rails控制台…toro2k是正确的,
.nil?
,而不是
.nil
。所以
(@stru value.index(“苹果”)).nil?(
等。这是三元语句的糟糕用法。使用一个,而不是多个。如果您觉得需要使用多个
If
case
语句。在Perl和C中,我们会大量使用它们,但这是Ruby。您确实希望避免嵌套的三元模式…您不应该在t中编写多个
条件?value1:value2
他的情况下,我认为@amit answer的更合适。是的,你对
nil
/
nil?
方法的看法是正确的。我只是想谈谈嵌套三元模式:)@Pierre LouisGottfrois你的第一个评论导致我投了反对票。这个答案不应该得到这样的答案(@Pierre LouisGottfrois Thank…:)“你的第一句话让我投了反对票。”?那就不要输入这样的代码。将你的错误选择归咎于评论人是愚蠢的,因为评论是正确的;嵌套三元在任何语言中都不好,尤其是在Ruby中都可以避免。这是第一个需要的重构,但作为字符串可能是第二个…这将返回
7
aswell@Pierre-路易斯戈特弗罗伊斯你是对的…:)但是对于长的词。。需要写入
|
@str_value.index(“XXXX”)
..的时间太多了我想。。我将使用数组。
NoMethodError:undefined方法“%”,用于/APPLE | DIAMOND | garmal/:Regexp
@AmitKumarGupta:对不起。修好了,很好!义务字符更好的是
/\b(?:APPLE | DIAMOND | garmal)\b/x
,它捕捉的不仅仅是子字符串,而是整个单词。@theTinMan:可能吧。但是我想写一些与原来的文章相同的东西(bug已经修复)
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%