【问题标题】:passing string as a condition of a method in ruby将字符串作为 ruby​​ 中方法的条件传递
【发布时间】:2017-05-12 04:09:03
【问题描述】:

有没有办法通过字符串操作来创建条件。这是我尝试将字符串作为条件传递给 include? 方法的代码。

"hello eveyone in the house".include?(%w('hello' 'world' 'new\ york'    'place').join(" || ").to_s)

【问题讨论】:

    标签: ruby-on-rails ruby conditional whitelist


    【解决方案1】:

    include? 的条件参数是不可能的,因为include? 只接受字符串参数。

    但是你可以这样写:

    ['hello', 'world', 'new york', 'place'].any? { |word|
      "hello everyone in the house".include?(word)
    }
    

    或者你可以从你的字符串生成一个正则表达式:

    "hello eveyone in the house".match?(
      /#{['hello', 'world', 'new york', 'place'].join('|')}/
    )
    

    【讨论】:

    • nince,但是你必须在 Ruby
    • 没错,match? 最近在 Ruby 2.4 中被引入。如果您使用的是旧版本,请改用match
    • 不错。如果您只需要一个布尔值作为答案,使用any? 的优点还在于它会在找到字符串后立即停止。
    • 谢谢,看来我正在尝试做一些你做不到的事情。
    【解决方案2】:

    另一种可能性是 split 单词并使用 set intersection

    sentence  = "hello everyone in the house"
    whitelist = %w(hello world new-york place)
    
    found_words = sentence.split & whitelist
    p found_words        # => ["hello"]
    p found_words.empty? # => false
    

    警告:仅当白名单不包含任何包含多个单词的字符串时才有效。例如new york 在原始问题中。

    有关更强大的解决方案,请参阅@spickermann 的回答。

    【讨论】:

    • 这不适用于包含多个单词的白名单术语(如本例中的new york)。因为在句子中new york 将被拆分为['new', 'york'] 并且不与数组[new york] 相交。
    【解决方案3】:

    做了一些基准测试来测试速度,令我惊讶的是,spickerman 的第一个解决方案是迄今为止在 windows 盒子上的 MRI Ruby 2.3.0 中最快的,其次是交集,而我自己的 Regexp.union 解决方案最后: (

    require 'benchmark' 
    
    s = "hello everyone in the house"
    a = ['hello', 'world', 'new york', 'place']
    
    N = 10_000
    
    Benchmark.bmbm do |x| 
      x.report("Union         ") { N.times { s.match(Regexp.union(a)) }}
      x.report("Union and scan") { N.times { s.scan(Regexp.union(a)) }}
      x.report("Interpollation") { N.times { s.match(/#{a.join('|')}/)}}
      x.report("intersect     ") { N.times { s.split & a }}
      x.report("block         ") { N.times { a.any? { |word| s.include?(word)}}}
    end 
    
    Rehearsal --------------------------------------------------
    Union            0.110000   0.000000   0.110000 (  0.116051)
    Union and scan   0.124000   0.000000   0.124000 (  0.121038)
    Interpollation   0.110000   0.000000   0.110000 (  0.105943)
    intersect        0.015000   0.000000   0.015000 (  0.018456)
    block            0.000000   0.000000   0.000000 (  0.001908)
    ----------------------------------------- total: 0.359000sec
    
                         user     system      total        real
    Union            0.109000   0.000000   0.109000 (  0.111704)
    Union and scan   0.125000   0.000000   0.125000 (  0.119122)
    Interpollation   0.109000   0.000000   0.109000 (  0.105288)
    intersect        0.016000   0.000000   0.016000 (  0.017283)
    block            0.000000   0.000000   0.000000 (  0.001764)
    

    【讨论】:

    • 尝试将“hello”放在a 的末尾,看看这对结果有何影响。事实上,@spickerman 的方法在处理完“hello”后退出,而其他方法继续运行。
    • 你编译N正则表达式,将Regexp.union移出循环,它可能是最快的。
    • 我对这个结果并不感到意外。与简单的字符串操作和字符串比较相比,构建正则表达式并启动“正则表达式引擎”非常昂贵。仅对于像这样的简单用例才值得,文本越长,条件越复杂,或者您重复使用相同的正则表达式的次数越多,正则表达式的回报就越多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 1970-01-01
    相关资源
    最近更新 更多