Ruby 如何正确使用地图和地图!方法

Ruby 如何正确使用地图和地图!方法,ruby,Ruby,我正在研究凯撒密码,这是一种真正简单的密码,它根据给定的密钥将消息中的每个字母向右移动。例如,如果密钥为3,则消息“hello”将被加密为“ifmmp” 我已经写了这个程序作为一系列的循环是。。。我忘了这个词,但它是一个循环中的一个循环。我一时想不起这个词 无论如何,我这样做的方式是首先将消息(可能由多个语句组成)转换为一个单词数组 然后,我将这些单词转换成一个字母数组,这样我就可以分别移动它们 最后,我将字母数组合并为单个单词,并将单词数组合并回单个消息 我遇到的问题是,每当我试图使用地图和地

我正在研究凯撒密码,这是一种真正简单的密码,它根据给定的密钥将消息中的每个字母向右移动。例如,如果密钥为3,则消息“hello”将被加密为“ifmmp”

我已经写了这个程序作为一系列的循环是。。。我忘了这个词,但它是一个循环中的一个循环。我一时想不起这个词

无论如何,我这样做的方式是首先将消息(可能由多个语句组成)转换为一个单词数组

然后,我将这些单词转换成一个字母数组,这样我就可以分别移动它们

最后,我将字母数组合并为单个单词,并将单词数组合并回单个消息

我遇到的问题是,每当我试图使用地图和地图!方法,我无法使移位的字母保持其值。我来自C/C++背景,在这些语言中,我这样做不会有问题,因为我了解指针和引用是如何工作的,但我不知道在Ruby中是如何工作的

我的问题是:如何使数组的值在循环内更改,并且在退出循环后不重置回其原始值?注释代码如下:

 def caesar_cipher(message,key)
    #Convert message to array
    message = message.split(' ')
    #Map each word in the array to the cipher method
    message.map! do |word|
        puts "message is: #{message} and the current word is: #{word}"
        #Split each word into an array of characters
        word = word.split('')           
        puts "after splitting word is: #{word.inspect}"
        #Map each letter to cipher function
        word.map do |letter|                
            puts "trying to shift the letter: #{letter.inspect}"
            #Based on the value of the key, each letter will be shifted to the right key times
            key.times do                    
                #Cases when the letter is at the end of the alphabet
                case letter
                when "z"
                    letter = "a"
                when "Z"
                    letter = "A"
                #By default, each letter will be shifted to the next letter in the alphabet per each iteration of the loop
                else 
                    letter = letter.next!
                end
                puts "the letter is now: #{letter.inspect}"
            end
            #Join the array of letters back into a single word
            word = word.join('')
            puts "after joining word is: #{word.inspect}"
        end
    end
    #Join the array of words back into the shifted message
    message.join(' ')
end               

你的代码基本上很好。我只做了两个小补丁

def caesar_cipher(message,key)
    message = message.split(' ')
    message.map! do |word|      
        word = word.split('')           
        word.map! do |letter| # or word = word.map                
            key.times do                    
                case letter
                when "z"
                    letter = "a"
                when "Z"
                    letter = "A"
                else 
                    letter = letter.next!
                end
            end
            letter # return the next letter from the block
        end
        word.join('')
    end
    message.join(' ')
end               

puts caesar_cipher('hello', 2)
# >> jgnnq
你做错了什么
  • 这些值没有保留更改,因为您没有保存它们(
    map
    不会更改原始数组,它会返回更改后的副本)
  • 有时,
    word.map
    的返回值是
    letter.next(因为它是块中计算的最后一个表达式),它是一个数字,而不是一个字母。你需要总是把信还给我

    • 这不是对这个问题的直接回答,但您可能会发现一种更实用的方法很有用

      我试图尽可能减少嵌套循环和条件分支逻辑,因为遵循它们可能会非常痛苦

      def caesar_cipher(message, key)
        key.times do 
          message = message
            .split("")   
            .map(&:ord)  # convert each character to ascii number
            .map(&:next) # increment ascii number by 1
            .map(&:chr)  # convert ascii number back to character
            .join        
            .gsub("{", "a") # fix characters out of range
            .gsub("[", "A")
        end
        message
      end
      

      我已经更新了缩进以反映实际代码。。。查看循环中不应该出现的问题-当试图找出问题所在时,通常最好使用
      put
      打印循环每次迭代中的当前消息/单词/字母,以查看每个循环得到的结果。。。它通常会非常清楚地说明问题所在。我会在你的代码中添加一些puts语句,你应该试着用它们运行它,看看输出是什么ruby注释不是这样工作的:)是的,对不起,我在发布代码之前添加了这些注释,我忘了ruby注释带有#。编辑以修复更常见的嵌套循环。太棒了!就是这样。。。谢谢你认为你能解释我做错了什么吗?我知道你在修改中发表了评论,但我不确定我所做的到底出了什么问题。用
      替换
      .map{digit | digit+=1}
      .map(&:next)
      @SergioTulentsev:啊,不错。