Ruby Итерирование по массиву и поиск соответствия в хэше и замена элемента в массиве - PullRequest
0 голосов
/ 11 ноября 2018

Мне бы хотелось, чтобы кто-то объяснил, как я могу выполнить итерацию по массиву, найти точное совпадение в хэше [значение] и заменить элемент в массиве хешем [ключ].

Например, если у меня есть каталог Морзе 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" => "-----" }

и я хочу метод, который для данной строки в коде Морзе возвращает строку в обычном алфавите. Это кодовые войны ката .

Меня не интересует решение самой задачи, я хотел бы понять принцип этого.

До сих пор я думал о том, чтобы поступить так:

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

Я печатаю только false, что означает, что я на самом деле не ищу совпадения в хэше.

Ответы [ 3 ]

0 голосов
/ 11 ноября 2018

при условии: 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)
0 голосов
/ 12 ноября 2018

Из ката я понимаю, что буквы должны быть разделены одним пробелом, а слова - тремя пробелами.

В качестве первого шага я внесу два изменения в хэш 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 используется при кодировании текста.Обратное значение этого хэша необходимо для декодирования сообщений в азбуке Морзе.Также для декодирования необходима пара ключ-значение "...---..."=>"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 См. вики.

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.Если это так, значение ключа - это азбука Морзе для слова;иначе слово делится на буквы, и каждая буква переводится на азбуку Морзе.

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" и ".".Я полагаю, что криптографы могли бы справиться с этим, но я решил избежать вставки пробела.

0 голосов
/ 11 ноября 2018

Использование Hash # key без замены массива, скорее создание нового (используйте 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 # invert и просто ссылаться на элементы по ключам по соображениям производительности, поскольку Hash#key равно O(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]
...