Ruby在数组上迭代,在哈希中找到匹配项,并替换数组中的元素



我希望有人澄清我如何可能在数组上迭代,在hash[value]中找到完全匹配的值,并用hash[key]替换数组中的元素。

例如,如果我有一个莫尔斯目录morse_dict = { "a" => ".-","b" => "-...","c" => "-.-.","d" => "-..","e" => ".","f" => "..-.","g" => "--.","h" => "....","i" => "..","j" => ".---","k" => "-.-","l" => ".-..","m" => "--","n" => "-.","o" => "---","p" => ".--.","q" => "--.-","r" => ".-.","s" => "...","t" => "-","u" => "..-","v" => "...-","w" => ".--","x" => "-..-","y" => "-.--","z" => "--.."," " => " ","1" => ".----","2" => "..---","3" => "...--","4" => "....-","5" => ".....","6" => "-....","7" => "--...","8" => "---..","9" => "----.","0" => "-----" }

我想要一个方法,对于莫尔斯电码中的给定字符串,返回正则字母表中的字符串。这是codewars kata。

我对挑战本身的解决方案不感兴趣,我想了解其中的原则。

到目前为止,我已经想过这样做:

def morse_code(arr)
arr.split(" ").each {|element| 
element.each_char {|char| 
(morse_dict.include?(char)) ? (print "true") : (print "false")}
}
end

我只打印false,这意味着我实际上并没有在散列中寻找匹配项。

使用Hash#密钥而不替换数组,而是创建一个新数组(使用map!进行替换(:

array = [1,2,3,4,5]    
hash = {a: 4, b: 7, c: 3}
array.map { |el| hash.key(el) }
# => [nil, nil, :c, :a, nil]

出于性能原因,您可能需要考虑使用Hash#inverse并简单地按键引用元素,因为Hash#keyO(n),而Hash#[]O(1)

array = [1,2,3,4,5]
hash = {a: 4, b: 7, c: 3}
inverted_hash = hash.invert
array.map { |el| inverted_hash[el] }
# => [nil, nil, :c, :a, nil]

我从kata中了解到,字母要用一个空格分隔,单词要用三个空格分隔。

作为第一步,我将对散列morse_dict进行两次更改:移除密钥' ';并为一些标点符号添加键值对。不需要空格字符键;文中讨论了标点符号的必要性。

PUNCTUATION = { "."=>".-.-.-", ","=>"--..--", "?"=>"..--..", "!"=>"-.-.--" }
ALPHA_TO_MORSE = dict.reject { |k,_| k == " " }.merge(PUNCTUATION)
#=> {"a"=>".-", "b"=>"-...", "c"=>"-.-.", "d"=>"-..", "e"=>".", "f"=>"..-.",
#    "g"=>"--.", "h"=>"....", "i"=>"..", "j"=>".---", "k"=>"-.-", "l"=>".-..", 
#    "m"=>"--", "n"=>"-.", "o"=>"---", "p"=>".--.", "q"=>"--.-", "r"=>".-.",
#    "s"=>"...", "t"=>"-", "u"=>"..-", "v"=>"...-", "w"=>".--", "x"=>"-..-",
#    "y"=>"-.--", "z"=>"--..", "1"=>".----", "2"=>"..---", "3"=>"...--",
#    "4"=>"....-", "5"=>".....", "6"=>"-....", "7"=>"--...", "8"=>"---..",
#    "9"=>"----.", "0"=>"-----", "."=>".-.-.-", ","=>"--..--", "?"=>"..--..",
#    "!"=>"-.-.--"}

我从莫尔斯电码维基获得了标点符号的莫尔斯电号。如果需要,可以添加其他标点符号。

散列ALPHA_TO_MORSE用于对文本进行编码。该散列的倒数用于解码莫尔斯电码中的消息。解码还需要密钥值对CCD_ 10。

MORSE_TO_ALPHA = ALPHA_TO_MORSE.invert.merge("...---..."=>"sos")
#=> {".-"=>"a", "-..."=>"b", "-.-."=>"c", "-.."=>"d", "."=>"e", "..-."=>"f",
#    "--."=>"g", "...."=>"h", ".."=>"i", ".---"=>"j", "-.-"=>"k", ".-.."=>"l",
#    "--"=>"m", "-."=>"n", "---"=>"o", ".--."=>"p", "--.-"=>"q", ".-."=>"r",
#    "..."=>"s", "-"=>"t", "..-"=>"u", "...-"=>"v", ".--"=>"w", "-..-"=>"x",
#    "-.--"=>"y", "--.."=>"z", ".----"=>"1", "..---"=>"2", "...--"=>"3",
#    "....-"=>"4", "....."=>"5", "-...."=>"6", "--..."=>"7", "---.."=>"8",
#    "----."=>"9", "-----"=>"0", ".-.-.-"=>".", "--..--"=>",",
#    "..--.."=>"?", "-.-.--"=>"!""...---..."=>"sos"}

还需要一个散列来处理消息"sos"(或"SOS"-莫尔斯码不区分大小写(或后面跟着标点符号(例如"sos!"(的"sos"要被编码的情况1请参阅Wiki。

SOS_WITH_PUNCTUATION = PUNCTUATION.each_with_object({}) { |(k,v),h|
h["sos#{k}"] = "...---... #{v}" }.merge('sos'=>"...---...")
#=> {"sos."=>"...---... .-.-.-", "sos,"=>"...---... --..--",
#    "sos?"=>"...---... ..--..", "sos!"=>"...---... -.-.--", "sos"=>"...---..."}

编码和解码方法如下。CCD_ 15检查字符串中的每个单词是否是散列CCD_。如果是,key的值就是单词的莫尔斯电码;否则,单词被分成字母,每个字母都被翻译成莫尔斯电码。

def encode(str)
str.strip.downcase.split.map do |word|
if SOS_WITH_PUNCTUATION.key?(word)
SOS_WITH_PUNCTUATION[word]
else
word.each_char.map { |c| ALPHA_TO_MORSE[c] }.join(' ')
end
end.join ('   ')
end
def decode(morse)
morse.strip.split(/ {3}/).map do |word|
word.split.map { |c| MORSE_TO_ALPHA[c] }.join
end.join(' ')
end

我们现在可以试试这两种方法。

str = "  Is now the time for   you, and 007, to send an SOS?"

morse = encode str
#=> ".. ...  -. --- .--  - .... .  - .. -- .  ..-. --- .-.  -.-- --- ..- --..--  .- -. -..  ----- ----- --... --..--  - ---  ... . -. -..  .- -.  ...---... ..--.."

decode morse
#=> "is now the time for you, and 007, to send an sos?"

有一个预处理步骤会更简单,例如将"sos."转换为"sos .",但当解码得到的莫尔斯电码时,"sos""."之间会有一个空间。我想密码学家可以处理这个问题,但我选择了避免插入空格

假设:arr = 'a b c d',它不是arr,所以请使morse_string

def morse_code(morse_string)
new_elements = []
# iterate over each character in the string, 
morse_string.split(" ").each do |element| 
if morse_dict[element]
# https://apidock.com/ruby/Array/push
new_elements.push( morse_dict[element] )
else
# whatever you want to do when there is no match
end
end
# re-create the string again, but with braille 
# https://apidock.com/ruby/Array/join
new_elements.join(' ')
end
morse_string = 'a b c d'
morse_code(morse_string)

最新更新