【问题标题】:Skipping to next vowel and consonant in a string跳到字符串中的下一个元音和辅音
【发布时间】:2017-08-02 15:33:20
【问题描述】:

我完成了一项包含以下说明的作业:

伪编码并编写一个方法,该方法采用间谍的真实姓名(例如,“Felicia Torres”)并通过执行以下操作创建一个假名:

交换名字和姓氏。 将所有元音(a、e、i、o 或 u)更改为 'aeiou' 中的下一个元音,并将所有辅音(除元音之外的所有其他字母)更改为字母表中的下一个辅音。

我的解决方案:

@vowels = %w(a e i o u)
@consonants = ("a".."z").to_a - @vowels

def next_vowel(letter)
  i = 0
  while i < @vowels.length
    if @vowels[i] == "u"
        return @vowels[0]
    elsif @vowels[i] == letter
        return @vowels[i+1]
    end
    i += 1
  end
end


def next_consonant(letter)
  i = 0
  while i < (@consonants.length)
    if @consonants[i] == "z"
        return @consonants[0]
    elsif @consonants[i] == letter
        return @consonants[i + 1]
    end
    i += 1
  end
end


def alias_manager(name)
    name.downcase!
    first_name = name.split(" ")[0]
    last_name = name.split(" ")[1]
    

    alias_first_name = last_name.chars.map do |i|
        if @vowels.include?(i)
            next_vowel(i)
        elsif @consonants.include?(i)
            next_consonant(i)
        end
    end
    
    
    alias_last_name = first_name.chars.map do |i|
        if @vowels.include?(i)
            next_vowel(i)
        elsif @consonants.include?(i)
            next_consonant(i)
        end
    end
   alias_first_name.join.capitalize! + " " + alias_last_name.join.capitalize!
end

我正在尝试用一种更简洁的方式来写这篇文章。 “while”循环似乎不是最有效的方法。我正在考虑使用“旋转”,但不确定如何替换字符串中的字母。另外,有没有办法重构 first_namelast_name 的最后一个迭代?我基本上为不同的变量写了两次相同的东西。

【问题讨论】:

    标签: arrays ruby string while-loop rotation


    【解决方案1】:

    定义next_vowelnext_consonant 的更好方法

        @vowels = %w(a e i o u)
        @consonants = ("a".."z").to_a - @vowels
    
        def next_vowel(letter)
          i = @vowels.index(letter)
    
          # Return the next vowel, using modulo for the last case (next of `u` is `a`)
          @vowels[(i + 1) % @vowels.length]
    
        end
    
        def next_consonant(letter)
          i = @consonants.index(letter)
    
          # Return the next vowel, using modulo for the last case (next of `z` is `b`)
          @consonants[(i + 1) % @consonants.length]
    
        end
    

    一些测试用例:

    2.3.3 :019 > next_vowel("a")
     => "e" 
    2.3.3 :020 > next_vowel("e")
     => "i" 
    2.3.3 :021 > next_vowel("u")
     => "a" 
    2.3.3 :022 > next_consonant("t")
     => "v" 
    2.3.3 :023 > next_consonant("z")
     => "b" 
    2.3.3 :024 > next_consonant("d")
     => "f" 
    

    【讨论】:

      【解决方案2】:

      听起来你的问题可能更适合https://codereview.stackexchange.com/

      也就是说 - 我建议您研究这两种方法:

      这可以将代码简化成这样:

      @vowels = %w( a e i o u )
      @consonants = ('a'..'z').to_a - @vowels
      
      def alias_manager(name)
        rotate_letters(name).split.reverse.map(&:capitalize).join(' ')
      end
      
      def rotate_letters(name)
        name.downcase.tr(@vowels.join, @vowels.rotate.join).tr(@consonants.join, @consonants.rotate.join)
      end
      

      【讨论】:

      • 这是迄今为止最好的答案。
      【解决方案3】:

      FWIW:

      VOWELS = %w(a e i o u) | %w(a e i o u).map(&:upcase)
      CONSONANTS = ((?a..?z).to_a | (?a..?z).map(&:upcase)) - VOWELS
      
      def next_elem letter
        array = VOWELS.include?(letter) ? VOWELS : CONSONANTS
        array.each_cons(2) { |me, they| break they if me == letter }
      end
      
      "Felicia Torres".split(' ').reverse.map do |l|
        l.split('').map(&method(:next_elem))
      end.map(&:join).join(' ')
      #⇒ "Vussit Gimodoe"
      

      【讨论】:

        【解决方案4】:

        此方法的设计考虑到了效率。这个想法是首先创建一个散列,在加密单个单词时进行字母映射(使用String#gsub 的形式,它使用散列进行替换)。这应该使加密非常快,当有很多字符串要加密时,这将特别有效。如下所述,使用散列的另一个好处是可以轻松创建解密加密字符串的方法。

        代码

        def create_hash(arr)
        puts "arr=#{arr}"
          (arr + [arr.first]).each_cons(2).with_object({}) { |(k,v),h| h[k]=v }
        end
        
        v = %w(a e i o u)
        c = ("a".."z").to_a - v
        subs_hash = create_hash(v).
                    merge(create_hash(v.map(&:upcase))).
                    merge(create_hash(c)).
                    merge(create_hash(c.map(&:upcase)))
          #=> {"a"=>"e", "e"=>"i", "i"=>"o", "o"=>"u", "u"=>"a",
          #    "A"=>"E", "E"=>"I", "I"=>"O", "O"=>"U", "U"=>"A",
          #    "b"=>"c", "c"=>"d", ..., "y"=>"z", "z"=>"b",
          #    "B"=>"C", "C"=>"D", ..., "Y"=>"Z", "Z"=>"B"} 
        
        def code(str, subs_hash)
          str.split.reverse.map { |word| word.gsub(/./, subs_hash) }.join(' ')
        end
        

        示例

        code("Felicia Torres", h)
          #=> "Vussit Gimodoe"
        code("eenie meanie", h)
          #=> "niepoi iipoi"
        

        解密加密字符串

        使用哈希的一个优点是它使编写decode 方法变得非常容易。

        inverted_subs_hash = subs_hash.invert
          #=> {"e"=>"a", "i"=>"e", "o"=>"i", "u"=>"o", "a"=>"u",
          #    "E"=>"A", "I"=>"E", "O"=>"I", "U"=>"O", "A"=>"U",
          #    "c"=>"b", "d"=>"c",..., "z"=>"y", "b"=>"z",
          #    "C"=>"B", "D"=>"C",..., "Z"=>"Y", "B"=>"Z"}
        
        def decode(str, inverted_subs_hash)
          code(str, inverted_subs_hash)
        end
        
        decode "Vussit Gimodoe", inverted_subs_hash
          #=> "Felicia Torres"
        

        大写和小写

        如果字符串首先被小写,则删除

        merge(create_hash(v.map(&:upcase))).
        

        merge(create_hash(c.map(&:upcase)))
        

        这样做会导致decode(code(str)) != str,除非我们假设每个单词的第一个字母大写并且所有其他字符都是小写,在这种情况下,我们可以通过应用使decode返回原始字符串(作为最后一步) String#capitalize 到每个解码的单词。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-11-16
          • 2021-06-20
          • 2017-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-24
          相关资源
          最近更新 更多