【问题标题】:Ruby: Pig Latin: Method to iterate through multiple words (not working)Ruby:Pig Latin:遍历多个单词的方法(不起作用)
【发布时间】:2013-04-30 07:09:56
【问题描述】:

抱歉,关于 TestFirst.org Ruby 练习编写“Pig Latin”方法的另一个问题,来自一个新手。其他答案有所帮助,但我无法成功适应它们。主要问题是我正在尝试编写一个方法来扫描一串单词(不仅仅是一个单词),修改一些单词(如果适用),然后返回完整的字符串。

下面是我尝试执行练习的第一部分的代码,即将“ay”附加到任何以元音开头的单词。但是,它对我不起作用-似乎是.include?与单个字母比较时永远不会返回 true(?)

非常感谢任何帮助!

# PIG LATIN
# If any word within the input string begins with a vowel, add an "ay" to the end of the word

def translate(string)

  vowels_array = %w{a e i o u y}
  consonants_array = ('a'..'z').to_a - vowels_array

  string_array = string.split

  string_array.each do |word|
    if vowels_array.include?(word[0])
      word + 'ay'
    end
  end

  return string_array.join(" ")

end 

translate("apple orange mango")    # => "appleay orangeay mango" but does not

【问题讨论】:

    标签: ruby


    【解决方案1】:

    string_array.each 只是遍历string_array,不会改变它;为了更新数组的内容,你应该使用map!:

      # ...
      string_array.map! do |word|
        if vowels_array.include?(word[0])
          word + 'ay'
        else
          word
        end
      end
      # ...
    
    translate("apple orange mango")    #=> "appleay orangeay mango"
    

    else word end 的目的是在不满足 if 条件时也返回单词。


    从数组操作的角度来看,在大多数情况下,操作字符串的最佳方式是正则表达式:

    def translate(string)
      string.gsub(/(^|\s)[aeiouy]\S*/i, '\0ay')
    end
    
    translate("apple orange mango") #=> "appleay orangeay mango"
    

    【讨论】:

    • @user2316803 如果你想使用一个数组,尽管你必须有一个临时数组来将修改后的对象推入。
    • @ProGNOMmers:啊,明白了——谢谢! (您上面的代码仍然不会在 Cadecademy 的 Ruby 1.8 控制台中返回修改后的字符串,但是当我在 cmd 中使用 Ruby 2.0 执行时可以正常工作)。 RegEx 替代方案对我来说太多了,但我明白了这个概念。再次感谢!
    • 正则表达式一开始很棘手,但是当你习惯它们时它们就会变得微不足道。不客气;-)
    【解决方案2】:

    哈希键查找may be a bit faster

    v= Hash['a', 1, 'o', '1', 'i', 1, 'u', 1, 'e', 1]
    ws= %w(apple orange mango)
    ws.map! do |w|
      v[w[0]].nil? ? w : "#{w}ay"
    end
    p ws
    

    【讨论】:

      【解决方案3】:

      听起来像是正则表达式的工作:

      str = 'apple orange mango'
      
      str.gsub(/\b[aeiou]\w*\b/, '\0ay')
      #=> "appleay orangeay mango"
      

      gsub 将查找所有出现的模式(第一个参数)并将其替换为字符串(第二个参数)。在该字符串中,您可以使用\0 引用匹配的模式并将ay 附加到它,这样我们就可以使用\0ay

      现在模式(实际的正则表达式)意味着“捕获整个单词(\b 匹配单词边界),以 [aeiou] 之一开头并以零个或多个单词字符结尾 (\w*)”。

      所以你的完整方法可以归结为:

      def translate(string)
        string.gsub /\b[aeiou]\w*\b/, '\0ay'
      end 
      

      瞧!

      【讨论】:

      • @paddle:感谢您的详尽解释。很棒的单线解决方案——它确实有效。需要了解更多关于正则表达式的信息!
      • 很高兴你喜欢它!或许可以考虑用赞成票来表达你的感激之情:)正则表达式确实很强大,但它们也可能会变得混乱,所以必须小心使用它们。
      • @paddle:我试过了,但还没有足够的代表这样做。即将发布另一个Q,所以很快就会回馈;)
      【解决方案4】:

      试试:

      def translate(string)     
        new_string = ''
        string.split.each do |word|
          if 'aoiue'.include?(word[0])
            new_string += word + 'ay '
          else
            new_string += word + ' '
          end
        end
        return new_string.strip
      end 
      
      > translate("apple orange mango")
      => "appleay orangeay mango" 
      

      【讨论】:

      • 太好了,这也有效(即使在 Ruby 1.8 下),而且很容易破译。唯一的问题是我们最终在字符串的末尾有一个额外的空格,但是'return new_string.chop'会处理这个问题。谢谢!
      猜你喜欢
      • 1970-01-01
      • 2014-08-15
      • 2013-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-26
      • 1970-01-01
      • 2020-07-19
      相关资源
      最近更新 更多