【问题标题】:Advancing Vowel to the Next Vowel in Ruby在 Ruby 中将元音推进到下一个元音
【发布时间】:2017-04-09 05:50:26
【问题描述】:

我正在编写初学者 Ruby 教程。我正在尝试编写一种将元音推进到下一个元音的方法。 'a' 会变成'e','e' 会变成'i','u' 会变成'a' 等等。我已经尝试了很长一段时间的各种想法,但无济于事。

我认为我走在正确的轨道上,因为我需要创建一个元音数组,然后使用索引将它们推进到元音中的下一个数组。我似乎无法创建正确的方法来做到这一点。

我知道这不是可行的代码,但我的大纲是这样的。我遇到问题的地方是让我的代码识别每个元音,并将其推进到下一个元音:

def vowel_adv(str)
    vowels = ["a", "e", "i", "o", "u"]

    str = str.split('')
    **str_new = str.map do |letter| 
    if str_new.include?(letter)
        str_new = str_new[+1]
    end**
    # The ** section is what I know I need to find working code with, but keep hitting a wall.
    str_new.join
end

任何帮助将不胜感激。

【问题讨论】:

    标签: ruby string


    【解决方案1】:

    因为我们只有几个元音,我会先定义一个包含元音键和元音值的哈希:

    vowels_hash = {
      'a' => 'e',
      'A' => 'E',
      'e' => 'i',
      'E' => 'I',
      'i' => 'o',
      'I' => 'O',
      'o' => 'u',
      'O' => 'U',
      'u' => 'a',
      'U' => 'A'
    }
    

    然后我会像这样遍历每个单词/句子中存在的字母:

    word.split(//).map do |character|
      vowels_hash[character] || character
    end.join
    

    更新:

    顺便说一句,您也可以将gsub 与正则表达式 + 哈希参数一起使用,而不是拆分单词,如下所示:

    word.gsub(/[aeiouAEIOU]/, vowels_hash)
    

    如果你想成为花式裤先生/女士,或者像这样:

    regex = /[#{vowels_hash.keys.join}]/
    word.gsub(regex, vowels_hash)
    

    【讨论】:

    • 很好地处理大写字母
    • 感谢@DaveSchweisguth。我想我们可以使用您与zip 一起共享的rotate 方法来生成vowels_hash,但在这种情况下只需输入它就更清楚了。
    • 这是包含大写字母的绝佳解决方案。我只是使用 .downcase 和 .capitalize,但这比我正在做的更灵活
    • 我赞赏你直接处理字符串,而不是“convert-to-array-manipulate-array-convert-back-to-string”舞蹈,并提供解决方案word.gsub(/[aeiou]/i, vowels_hash) ,但其余的只是分散注意力,削弱你的答案。读者会问,“那么,你推荐什么?”。这里少即是多。另外,为什么要“更新:”?
    • @CarySwoveland 我首先想出了分裂的答案;添加字符串操作方法作为编辑,因此更新。
    【解决方案2】:

    这是您的代码,只需最少的更正即可使其正常工作:

    def vowel_adv(str)
      vowels = ["a", "e", "i", "o", "u"]
      str = str.split('')
      str_new = str.map do |char|
        if vowels.include?(char)
          vowels.rotate(1)[vowels.index(char)]
        else
          char
        end
      end
      str_new.join
    end
    vowel_adv "aeiou"
    => "eioua"
    

    我更改的内容包括

    • map 块添加块变量
    • map 块中返回要映射到的对象
    • include? 是在 Array 上调用的,而不是在可能的元素上调用
    • 通过在元音数组中查找下一个元音,而不是通过增加字符,我认为您正在尝试这样做。

    这是一个改进的版本:

    VOWELS = %w(a e i o u)
    ROTATED_VOWELS = VOWELS.rotate 1
    
    def vowel_adv(str)
      str.
        chars.
        map do |char|
          index = VOWELS.index char
          if index
            ROTATED_VOWELS[index]
          else
            char
          end
        end.
        join
    end
    
    • 常量中的静态Arrays
    • 更好的字符串数组语法
    • String#chars 而不是 split
    • 使用索引来测试包含而不是include?
    • 没有给参数赋值,这有点混乱
    • 没有临时变量,有些人喜欢,有些人不喜欢,但我在此展示了这是可能的

    而且,因为 Ruby 很有趣,这里有一个不同的版本,它复制字符串并修改副本:

    VOWELS = %w(a e i o u)
    ROTATED_VOWELS = VOWELS.rotate 1
    
    def vowel_adv(str)
      new_str = str.dup
      new_str.each_char.with_index do |char, i|
        index = VOWELS.index char
        if index
          new_str[i] = ROTATED_VOWELS[index]
        end
      end
      new_str
    end
    

    【讨论】:

    • 非常感谢!我还没有遇到 .rotate ,现在只是在 Ruby Doc 中查找它,它似乎正是我需要的方法。这完全符合我的要求。
    【解决方案3】:

    字符串类为此有一个nice method。演示:

    p "Oh, just a test".tr("aeiouAEIOU", "uaeioUAEIO") # => "Ih, jost u tast"
    

    【讨论】:

      【解决方案4】:

      到 steenslag 的回答的 riff 一点。

      VOWELS = %w{a e i o u A E I O U} 
      SHIFTED_VOWELS = VOWELS.rotate 1
      
      def vowel_shifter input_string
        input_string.tr!(VOWELS.join, SHIFTED_VOWELS.join)
      end
      

      只是为了好玩,辅音:

      CONSONANTS = ('a'..'z').to_a + ('A'..'Z').to_a - VOWELS
      SHIFTED_CONSONANTS = CONSONANTS.rotate 1
      
      def consonant_shifter input_string
        input_string.tr!(CONSONANTS.join, SHIFTED_CONSONANTS.join)
      end
      

      【讨论】:

        猜你喜欢
        • 2017-08-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-16
        • 1970-01-01
        • 2018-01-28
        • 1970-01-01
        • 2014-02-13
        相关资源
        最近更新 更多