【问题标题】:Ruby - arrays check for and replace withRuby - 数组检查并替换为
【发布时间】:2015-04-28 11:46:38
【问题描述】:

给定:

check_for = ["Lorem", "ipsum", "dolor", "sit", "amet"]

replace_with = ["Donec", "ut", "libero", "sed", "arcu"]

sentence = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur."

如果'sentence'中包含放置在数组'check_for'中的单词,我如何检查整个字符串,如果找到,则替换为'replace_with'中的单词?

check_for 中的单词可以替换为 replace_with 中具有相同索引的单词:

check_for[idx] 应替换为 replace_with[idx]

我使用嵌套循环对 Javascript 做了一些“类似”的事情。由于某种原因,这不适用于 Ruby。

我对嵌套循环的想法是将句子拆分为数组并使用带有 i 和 j 的 while 循环。所以 sentence[i] 将从 0 开始:

sentence[i] == check_for[j]

然后:

sentence[i] = replace_with[j]

除了这个想法不起作用之外,我确信在 Ruby 中还有更直接的方法。

不区分大小写是可以的。

【问题讨论】:

    标签: javascript ruby arrays loops replace


    【解决方案1】:

    这可以通过定义替换的哈希来完成:

    sentence = "Lorem ipsum dolor sit amet, consectetur adipiscing elit..."
    replacements = {
      'Lorem' => 'Donec',
      'ipsum' => 'ut',
      'dolor' => 'libero',
      'sit'   => 'sed',
      'amet'  => 'arcu',
    }
    
    sentence.gsub(Regexp.union(replacements.keys), replacements)
    #=> "Donec ut libero sed arcu, consectetur adipiscing elit..."
    

    顺便说一句,您可以像这样从数组中轻松生成 replacements 哈希:

    replacements = Hash[check_for.zip(replace_with)]
    

    Cary Swoveland 建议使用简化的正则表达式:

    sentence.gsub(/\w+/, replacements)
    

    我真的很喜欢这样,因为它读起来更好看。

    我想知道 rexexp 是否对性能有影响:一方面是构建一个复杂但专门的正则表达式。另一方面使用简单的正则表达式,但必须根据哈希检查每个单词。

    require 'benchmark'
    
    def simple
      @sentence.gsub(/\w+/, @replacements)
    end
    
    def union
      @sentence.gsub(Regexp.union(@replacements.keys), @replacements)
    end
    
    n = 100_000
    Benchmark.bmbm(15) do |x|
      x.report("simple :")   { n.times do; simple; end }
      x.report("union  :")   { n.times do; union ; end }
    end
    
    # Rehearsal ---------------------------------------------------
    # simple :          4.790000   0.010000   4.800000 (  4.804576)
    # union  :          3.820000   0.020000   3.840000 (  3.846012)
    # ------------------------------------------ total: 8.640000sec
    

    事实证明,较长的版本更快一些。但我很确定这可能会根据sentence 的长度和要替换的元素数量而改变。

    【讨论】:

    • 你也可以写sentence.gsub(/\w+/, replacements),因为只有匹配哈希键的单词才会被替换。
    【解决方案2】:

    这是一种无需替换哈希的方法,使用#index method

    replaced_sentence = []
    sentence.split.each do |word|
    
      if idx = check_for.index(word.match(/\w+/).to_s) 
        replaced_sentence << word.gsub((/\w+/) , replace_with[idx] )
        else
         replaced_sentence << word
        end
     end
    
    replaced_sentence.join(' ')
    #=> "Donec ut libero sed amet, consectetur adipiscing elit..."
    

    这会遍历句子的每个单词。如果check_for 包含单词(减去标点符号),则check_for.index(word...) 返回该索引值。然后将该索引值分配给idxreplace_with[idx] 的值替换单词并“推送”到新的replaced_sentence 数组。

    如果单词不匹配,check_for.index(word) 返回nil,这会导致if 语句不成立,并且原始word 被推送到新数组。

    【讨论】:

    • 我采用了spikermann的方法,但我真的很喜欢这个。尽管它仍然与我的嵌套循环想法不同,但这几乎就是我的想法。
    • 我意识到我的解决方案没有考虑标点符号。我现在需要使用一个小的 RegEx。我已经更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 2015-04-11
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    相关资源
    最近更新 更多