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

时间:2015-07-30 04:23:31

标签: ruby

我正在研究凯撒密码,这是一个真正简单的密码,它根据给定的密钥将消息中的每个字母移动到右边。例如,如果键为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               

2 个答案:

答案 0 :(得分:2)

你的代码很好。我只做了两个小修补

Debug.Print()

你做错了什么

  • 这些值没有保留更改,因为您没有保存它们(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(因为它是块中评估的最后一个表达式),这是一个数字,而不是字母。你需要随时归还这封信。

答案 1 :(得分:0)

不是问题的直接答案,但您可能会发现一种更有用的功能方法。

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

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