2014-09-30 75 views
0

我正在嘗試編寫凱撒密碼,但我試圖解決映射循環中使用的正則表達式問題。我的代碼是:正則表達式和映射問題

class Cipher 

    attr_reader :string 
    attr_reader :factor 

    def initialize(string, factor) 
    @string = string 
    @factor = factor 
    end 

    def factored_ascii 
    @string.chars.map do |letter| 
     value = letter.ord + (@factor % 26) 

     if letter =~ /[a-z]/ && value > 122 
     value = (value % 122) + 96 

     elsif letter =~ /[A-Z]/ && value > 90 
     value = (value % 90) + 64 

     elsif letter =~ /[^A-Za-z]/ 
     value = letter.ord 
     end 
    end 
    end 
end 

當字符串參數「什麼的字符串」,它只有在正確的第一W字符和空格字符操作的對象調用factored_ascii,設置其他元素尼爾斯。

[66, nil, nil, nil, 32, nil, 32, nil, nil, nil, nil, nil, nil] 

我很可能做一些相當愚蠢的事情。你能否幫助啓發我,並且爲了解決這個問題而節省更多的時間?

+0

我無法理解你想要的結果,但我可以解釋你爲什麼得到nils。你的問題在if語句中:它沒有捕獲所有其他情況的'else'塊。結果你的迭代對大多數字符返回nil。注意最後一個正則表達式'/ [^ A-Za-z] /'有'^'這意味着行首! – gotva 2014-09-30 12:48:05

+1

@gotva'^'裏面的[]'表示否定不起動 – vks 2014-09-30 13:04:18

+0

哦,你說得對。但我認爲這並沒有改變這種情況。它看起來像大多數字母不被條件內的條件捕獲。 – gotva 2014-09-30 13:08:07

回答

1

map將值映射到由塊返回的值。除非顯式返回一個值,否則塊的返回值是最後執行的語句的值。在你的情況下,這是if語句。如果沒有符合條件,則返回nil

例如:

x = [1,2,3,4] 
x.map do |y| 
    if y % 2 == 0 
    y 
    end 
end 
# [nil, 2, nil, 4] 

查看所有不符合條件的值怎麼弄nil?要修復你的代碼,只需在if語句後面加上value,這可以確保它始終是返回值。

1

@Max已經回答了你的問題,但你可能要考慮不同的書寫方法:

def factored_ascii 
    @string.chars.map do |letter| 
    value = letter.ord + (@factor % 26) 
    case(letter)    
    when /[a-z]/ && value > 122 
     (value % 122) + 96 
    when /[A-Z]/ && value > 90 
     (value % 90) + 64 
    when /[^A-Za-z]/ 
     letter.ord 
    else 
     value 
    end 
    end 
end 

@string = "aZr$" 
@factor = 0 
factored_ascii #=> [97, 90, 114, 36] 

這工作,因爲case語句使用===(這裏Regexp#===)的比較(例如,when /[a-z]/相當於letter =~ /[a-z]/)。