Извлечение ключей путем сравнения значений на карте

#erlang #erlang-shell

#erlang #erlang-оболочка

Вопрос:

Я пытаюсь распечатать ключи, сравнивая значения карты с заданными входными данными в виде строки (входные данные приведены в приведенном ниже примере примерного вывода).

Смотрите приведенный ниже код, который я пробовал кодировать:

 -module(main).
-compile(export_all).
 get_code_for_words(Sentence) ->
   Words = string:split(Sentence, "s", all),
   LettersWords = # { "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" =>"--.. "},
   Result = get_codes(Words, LettersWords, _AllCodes=[]),
   io:format("~p~n", [Result]).
            
 get_codes([Word|Words], Map, AllCodes) ->
    NewAllCodes = maps:fold(fun(K,V,Acc) ->
                           %io:format("~p~n",[Acc]),
                           case V =:= Word of
                                true -> [K|Acc];
                                _    -> Acc
                           end
                       end,
                       AllCodes,
                       Map),
            get_codes(Words, Map, NewAllCodes);
        get_codes([], _Map, AllCodes) ->
            lists:reverse(AllCodes).
 

Когда я выполнил код, результат приведен ниже:

 **

9> c(main).                           
    main.erl:2: Warning: export_all flag enabled - all functions will be exported
    {ok,main}
    10> main:get_code_for_words(".... ..").
    []
    ok
 

**

Пожалуйста, предложите мне?

Комментарии:

1. Спасибо 7stud за расширение, я попробовал с помощью предоставленного вами примера функции get_code_for_words(предложение) делает то, о чем я прошу. Функция берет предложение и разбивает его на слова, затем берет каждое слово по очереди и просматривает каждое значение на карте, чтобы найти совпадения для слова, и если совпадение найдено, ключ для соответствующего значения добавляется в накопитель. Он работает правильно, но вывод печатается. Пожалуйста, предложите мне?

2. Ни одно из значений на вашей карте не является "...." or ".." , так каким вы ожидаете получить результат?

3. В определенной карте («a» => «.- «,»b» =>»-… «,) , Я просто удалил лишнее пространство в значении Map(И моя Карта будет («a» => «.- «,»b» =>»-…»,). Затем значение сравнивается с вводом, я выполнил и получил требуемый результат. Спасибо @7Stud.

Ответ №1:

Давайте сначала переформатируем ваш код (с помощью rebar3_format ):

 get_code_for_words(Sentence) ->
    Words = string:split(Sentence, "s", all),
    LettersWords =
        #{"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" => "--.. "},
    Result = get_codes(Words, LettersWords, _AllCodes = []),
    io:format("~p~n", [Result]).

get_codes([Word | Words], Map, AllCodes) ->
    NewAllCodes =
        maps:fold(fun(K, V, Acc) ->
                     case V =:= Word of
                         true -> [K | Acc];
                         _ -> Acc
                     end
                  end,
                  AllCodes,
                  Map),
    get_codes(Words, Map, NewAllCodes);
get_codes([], _Map, AllCodes) ->
    lists:reverse(AllCodes).
 

Теперь давайте изолируем карту, чтобы мне не приходилось постоянно копировать ее, и, поскольку это не похоже на escript, давайте просто удалим вызов io:format/2 для результата…

 letters_to_words() ->
        #{"a" => ".- ",
…
          "z" => "--.. "}.

get_code_for_words(Sentence) ->
    Words = string:split(Sentence, "s", all),
    get_codes(Words, letters_to_words(), _AllCodes = []).
 

Теперь давайте поговорим о get_codes/3
Поскольку эта функция использует приведенную выше карту, я предполагаю, что вы, когда говорите Word , на самом деле имеете в виду Character (поскольку в противном случае вам придется переходить от символа к символу, но эта функция выполняется слово за словом)…

Давайте сначала используем сопоставление с образцом вместо логического case оператора…

 get_codes([Word | Words], Map, AllCodes) ->
    NewAllCodes =
        maps:fold(fun(K, V, Acc) ->
                     case V of
                         Word -> [K | Acc];
                         _ -> Acc
                     end
                  end,
                  AllCodes,
                  Map),
    get_codes(Words, Map, NewAllCodes);
get_codes([], _Map, AllCodes) ->
    lists:reverse(AllCodes).
 

Теперь я предполагаю, что вы ожидаете, что это произойдет…

 8> a_module:get_code_for_words(".- -.-.").
["a","c"]
 

Но вместо этого вы получаете…

 8> a_module:get_code_for_words(".- -.-.").
[]
 

И, чтобы понять, почему это происходит, давайте посмотрим, каков результат string:split/3 в вашем случае…

 9> string:split(".- -.-.", "s", all).    
[".-","-.-."]
 

Как вы можете видеть, в этих строках нет конечных пробелов, как в ключах на вашей карте. Итак … замена вашей карты на следующую должна решить вашу проблему…

 letters_to_words() ->
        #{"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. Спасибо @Brujo Benavides за это «Как вы можете видеть, в этих строках нет конечных пробелов, как в ключах на вашей карте. Итак … замена вашей карты на следующую должна решить вашу проблему …» на самом деле это решило мою проблему и отлично ее выполнило.