Ruby遍历数组,在哈希中找到匹配项,并替换数组中的元素

时间:2018-11-11 19:12:51

标签: arrays ruby hash iteration

我希望有人阐明如何迭代数组,在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" => "-----" }

,我想要一个方法,对于摩尔斯电码中的给定字符串,它以常规字母形式返回字符串。 This is the codewars kata

我对挑战本身的解决方案不感兴趣,我想了解这一原理。

到目前为止,我已经考虑过以这种方式进行操作:

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

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

3 个答案:

答案 0 :(得分:1)

使用Hash#key而不替换数组,而是创建一个新数组(使用const workflows = [{ id: 1, workflow: 'bookeeping', statuses: [{ status: 'Received' }, { status: 'Prepare' }, { status: 'Review' }, { status: 'Complete' }, ] }, { id: 2, workflow: 'payroll', statuses: [{ status: 'Received' }, { status: 'Scan' }, { status: 'Enter Data' }, { status: 'Review' }, { status: 'Complete' }, ] }, { id: 3, workflow: 'tax preparation', statuses: [{ status: 'Received' }, { status: 'Scan' }, { status: 'Prep' }, { status: 'Review' }, { status: 'Complete' }, ] }, ]; const engagements = [{ engagement: '1040', workflow_id: 1, status: 'Received' }, { engagement: '1040', workflow_id: 1, status: 'Received' }, { engagement: '1040', workflow_id: 1, status: 'Review' }, { engagement: '1040', workflow_id: 2, status: 'Review' }, { engagement: '1040', workflow_id: 2, status: 'Complete' }, { engagement: '1040', workflow_id: 2, status: 'Complete' }, { engagement: '1040', workflow_id: 3, status: 'Prep' }, { engagement: '1040', workflow_id: 3, status: 'Prep' }, { engagement: '1040', workflow_id: 2, status: 'Enter Data' }, { engagement: '1040', workflow_id: 2, status: 'Enter Data' }, { engagement: '1040', workflow_id: 2, status: 'Enter Data' }, { engagement: '1040', workflow_id: 1, status: 'Prepare' }, { engagement: '1040', workflow_id: 1, status: 'Prepare' }, ]; const res = workflows.map(({statuses, id}) => ({ workflow_id: id, statuses: statuses.reduce((acc, cur) => { const count = engagements.filter(({workflow_id, status}) => workflow_id === id && status === cur.status).length; if(count === 0) return acc; acc.push({status: cur.status, count}); return acc; }, []) })) console.log(res);进行替换):

map!

出于性能原因,您可能要考虑使用Hash#invert并仅通过键引用元素,因为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#keyO(n)Hash#[]

O(1)

答案 1 :(得分:0)

假设:c:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe,不是arr,所以请输入morse_string

-Command

答案 2 :(得分:0)

从片文中我知道字母要用一个空格隔开,单词要用三个空格隔开。

第一步,我将对哈希morse_dict进行两次更改:删除键' ';并为某些标点符号添加键值对。不需要空格字符键; kata中讨论了标点符号的需要。

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"=>"-----", "."=>".-.-.-", ","=>"--..--", "?"=>"..--..",
  #    "!"=>"-.-.--"}

我从Morse Code Wiki获得了标点字符的摩尔斯电码。如果需要,可以添加其他标点符号。

哈希ALPHA_TO_MORSE用于编码文本。要解码摩尔斯电码中的消息,需要使用此哈希的逆函数。密钥对"...---..."=>"sos"也需要解码。

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"=>"...---..."}

编码和解码方法如下。 encode检查字符串中的每个单词是否是哈希SOS_WITH_PUNCTUATION中的键。如果是,则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?"

1拥有一个将"sos."转换为"sos ."的预处理步骤会更简单,但是当对所得的摩尔斯电码进行解码时, "sos""."。我想密码学家可以解决这个问题,但是我选择避免插入空格。