Erlang代码将不带分隔符的String拆分并放入列表

时间:2018-08-04 15:54:11

标签: erlang

我对使用Erlang编程非常陌生。 我正在编写一个程序来解码盲文,但在尝试在没有分隔符的情况下每2个字符分割一个字符串并将其放入列表时遇到了问题。

首先,我这样读盲文字母:

inKey(Key1) -> Key1.
inKey2(Key2) -> Key2.
inKey3(Key3) -> Key3.

键1-3是字符串,看起来像这样:"x.x.xxxxx.xxxxx..x.xx.x.xxxxx.xxxxx..x.xx.x..xxxxxx."这3个键构成了盲文信息,我将在稍后使用该信息将盲文转换为普通字符。

现在,我需要分割此字符串并将其放置在列表中,以使其看起来像这样:["x.","x.","xx","xx",x.","xx","xx","x.",".x,依此类推。

如果字符串被分割,我想将其插入到我的编码列表中,如Tuplet中显示的字符A

 Code=[#row{name="R1",alfabet=[#codes{letter="A",braille="X."},#codes{letter="B",braille=""}

有人可以帮我吗?

`

2 个答案:

答案 0 :(得分:5)

在Erlang中,您需要记住一个字符串等效于数字列表,其中数字是每个字符的ASCII码。令人困惑的是,有时外壳程序将数字列表显示为字符串,有时将数字列表显示为数字列表。那是erlang shell的一个可怕特性。

尽管外壳显示了什么,但请记住,字符串是数字列表。问题就变成了,如果您要输出数字列表而不是字符串怎么办?答案是:您对此无能为力。外壳可能会将您的数字列表显示为字符串...除非您采取进一步的措施:

45> Grades = [97,98,99].
"abc"

Wtf ??!

46> io:format("~w~n", [Grades]).
[97,98,99]
ok

另一种思考方式是:erlang字符串语法"abc"只是创建数字列表[97,98,99]的快捷方式。

接下来,您可以使用以下模式解构列表:

[Head|Tail] = [1,2,3]

在外壳中:

8> [Head|Tail] = [1, 2, 3, 4].
[1,2,3,4]

9> Head.                      
1

10> Tail.
[2,3,4]

但是,cons运算符|比这更灵活,并且它允许您执行以下操作:

13> [N1,N2 | T] = [1, 2, 3, 4].   
[1,2,3,4]

14> N1.
1

15> N2.
2

16> T.
[3,4]

因此,您可以执行以下操作:

-module(my).
-compile(export_all).

string() ->
    "x.x.xxxxx.xxxxx..x.xx.x.xxxxx.xxxxx..x.xx.x..xxxxxx.".

chunk2([]) -> [];
chunk2([N1, N2| Tail]) ->
    [[N1,N2] | chunk2(Tail) ].

在外壳中:

2> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}

3> my:chunk2(my:string()).  
["x.","x.","xx","xx","x.","xx","xx","x.",".x",".x","x.",
 "x.","xx","xx","x.","xx","xx","x.",".x",".x","x.","x.",".x",
 "xx","xx","x."]

4> 

最后,要构建#code{}记录的列表,可以执行以下操作:

-module(my).
-compile(export_all).
-record(codes, {letter, braille}).

string() ->
    "x.x.xxxxx.xxxxx..x.xx.x.xxxxx.xxxxx..x.xx.x..xxxxxx.".

chunk2([]) -> [];
chunk2([N1, N2| Tail]) ->
    [[N1,N2] | chunk2(Tail) ].

make_record_list(Letters, Chunks) ->
    lists:zipwith(
        fun(Letter, Chunk) -> #codes{letter=[Letter], braille=Chunk} end,
        Letters,
        Chunks
    ).

在外壳中:

31> c(my).             
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}

32> ListOfCapLetters = lists:seq($A, $Z).
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"

33> BrailleChunks = my:chunk2(my:string()).
["x.","x.","xx","xx","x.","xx","xx","x.",".x",".x","x.",
 "x.","xx","xx","x.","xx","xx","x.",".x",".x","x.","x.",".x",
 "xx","xx","x."]

34> Records = my:make_record_list(ListOfCapLetters, BrailleChunks).
[{codes,"A","x."},
 {codes,"B","x."},
 {codes,"C","xx"},
 {codes,"D","xx"},
 {codes,"E","x."},
 {codes,"F","xx"},
 {codes,"G","xx"},
 {codes,"H","x."},
 {codes,"I",".x"},
 {codes,"J",".x"},
 {codes,"K","x."},
 {codes,"L","x."},
 {codes,"M","xx"},
 {codes,"N","xx"},
 {codes,"O","x."},
 {codes,"P","xx"},
 {codes,"Q","xx"},
 {codes,"R","x."},
 {codes,"S",".x"},
 {codes,"T",".x"},
 {codes,"U","x."},
 {codes,"V","x."},
 {codes,"W",".x"},
 {codes,"X","xx"},
 {codes,"Y","xx"},
 {codes,"Z",[...]}]

最后一条记录似乎有问题,让我们检查一下:

37> tl(Records).  
[{codes,"B","x."},
 {codes,"C","xx"},
 {codes,"D","xx"},
 {codes,"E","x."},
 {codes,"F","xx"},
 {codes,"G","xx"},
 {codes,"H","x."},
 {codes,"I",".x"},
 {codes,"J",".x"},
 {codes,"K","x."},
 {codes,"L","x."},
 {codes,"M","xx"},
 {codes,"N","xx"},
 {codes,"O","x."},
 {codes,"P","xx"},
 {codes,"Q","xx"},
 {codes,"R","x."},
 {codes,"S",".x"},
 {codes,"T",".x"},
 {codes,"U","x."},
 {codes,"V","x."},
 {codes,"W",".x"},
 {codes,"X","xx"},
 {codes,"Y","xx"},
 {codes,"Z","x."}]

不是,第一个输出刚刚达到了外壳程序愿意显示的极限。

请注意,ListOfCapLetters的每个元素都是一个数字,而数字不是列表,因此ListOfCapLetters的每个元素本身都不是字符串。要根据数字创建字符串,您需要将其放入列表中,因此要放在[Letter]中。 String = [97,98,99]ListOfStrings = [[97], [98], [99]]之间是相同的区别:

40> String = [97,98,99].
"abc"

41> hd(String).
97

42> ListOfStrings = [[97], [98], [99]].
["a","b","c"]

43> hd(ListOfStrings).
"a"

lists:seq()返回等效的String。

回复评论:

请参见lists:keyfind/3

20> TargetRecord = lists:keyfind("xx", 3, Records).                
#codes{letter = "C",braille = "xx"}

21> rr(my).  %Read record definition contained in my.erl into the shell.                                                     
[codes]

22> TargetRecord#codes.letter.
"C"

字符串"C"实际上是列表[67],shell已决定将其显示为“ C”。您需要能够查找一个ascii表,以发现一个字符串在Erlang中真正代表了什么。或者,您可以获取这样的字符的ASCII代码:

24> $C.
67

25> $a.
97

因此,"C"实际上是列表[67],而"a"实际上是列表[97]。

答案 1 :(得分:2)

发布此消息已为时已晚,但是我这样做是因为我认为要用于存储字母的变量类型实际上并不适合您可能使用的不同用法。我编写了一个小代码来显示两个映射的用法(一个用于解码,一个用于编码)。 对不起,代码中只有几个注释

-module (braille).

-export ([test/1,show_maps/0]).

test(Str) ->
    % build the conversion map
    {Alphabet,Braille} = init(),
    % transform a string into braille and print it
    Lines = print_braille(Str,Alphabet),
    % transform the braille result into string , check the result and print it
    Str = read_braille(Lines,Braille),
    ok.

show_maps() ->
    {Alphabet,Braille} =init(),
    io:format("Alphabet = ~n~100p~n~nBraille = ~n~100p~n",[Alphabet,Braille]).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% creates one map to allow the conversion from latin letter to braille: Alphabet
%     and one map to allow the conversion from braille to latin : Braille
% This should be the init function of a conversion server, in charge to maintain the conversion maps
init() ->
    L1="x.x.xxxxx.xxxxx..x.xx.x.xxxxx.xxxxx..x.xx.x..xxxxxx.",
    L2="..x....x.xx.xxxxx.xx..x....x.xx.xxxxx.xx..x.xx...x.x",
    L3="....................x.x.x.x.x.x.x.x.x.x.xxxx.xxxxxxx",

    LL1 = split_str(L1),
    LL2 = split_str(L2),
    LL3 = split_str(L3),

    Alphabet = init_alphabet(LL1,LL2,LL3,$a,#{$ => #{1 => "..", 2 => "..", 3=> ".."}}),
    Braille = init_braille(Alphabet),
    {Alphabet,Braille}.

% a tail recursive function to split the input string into packets of 2 characters
split_str_tail_recursive([],R) ->
    lists:reverse(R);
split_str_tail_recursive([A,B|Rest],R) ->
    split_str_tail_recursive(Rest,[[A,B]|R]).
% interface to call the recursive fuction
split_str(L) -> split_str_tail_recursive(L,[]).

init_alphabet([],[],[],_,R) ->
    R;
init_alphabet([H1|T1],[H2|T2],[H3|T3],C,R) ->
    init_alphabet(T1,T2,T3,C+1,maps:put(C,#{1 => H1, 2 => H2, 3=> H3},R)).

init_braille(Alphabet) ->
    H = fun(K,V,AccIn) -> maps:put({maps:get(1,V),maps:get(2,V),maps:get(3,V)},K,AccIn) end,
    maps:fold(H,#{},Alphabet).

%transform a latin lower cap string into 3 lines representing a braille output, print them and returns the 3 lines
print_braille(S,Alphabet) ->
    Line1 = lists:flatmap(fun(C) -> maps:get(1,maps:get(C,Alphabet)) end,S),
    Line2 = lists:flatmap(fun(C) -> maps:get(2,maps:get(C,Alphabet)) end,S),
    Line3 = lists:flatmap(fun(C) -> maps:get(3,maps:get(C,Alphabet)) end,S),
    io:format("~s~n~s~n~s~n",[Line1,Line2,Line3]),
    {Line1,Line2,Line3}.

% transform a tuple of 3 lines braille representation into latin string, print it and return it
read_braille({Line1,Line2,Line3},Braille) ->
    List = lists:zip3(split_str(Line1),split_str(Line2),split_str(Line3)),
    Str = lists:map(fun(B) -> maps:get(B,Braille) end,List),
    io:format("~s~n", [Str]),
    Str.

这里是用法:

1> c(braille).
{ok,braille}
2> braille:show_maps().
Alphabet = 
#{32 => #{1 => "..",2 => "..",3 => ".."},
  97 => #{1 => "x.",2 => "..",3 => ".."},
  98 => #{1 => "x.",2 => "x.",3 => ".."},
  99 => #{1 => "xx",2 => "..",3 => ".."},
  100 => #{1 => "xx",2 => ".x",3 => ".."},
  101 => #{1 => "x.",2 => ".x",3 => ".."},
  102 => #{1 => "xx",2 => "x.",3 => ".."},
  103 => #{1 => "xx",2 => "xx",3 => ".."},
  104 => #{1 => "x.",2 => "xx",3 => ".."},
  105 => #{1 => ".x",2 => "x.",3 => ".."},
  106 => #{1 => ".x",2 => "xx",3 => ".."},
  107 => #{1 => "x.",2 => "..",3 => "x."},
  108 => #{1 => "x.",2 => "x.",3 => "x."},
  109 => #{1 => "xx",2 => "..",3 => "x."},
  110 => #{1 => "xx",2 => ".x",3 => "x."},
  111 => #{1 => "x.",2 => ".x",3 => "x."},
  112 => #{1 => "xx",2 => "x.",3 => "x."},
  113 => #{1 => "xx",2 => "xx",3 => "x."},
  114 => #{1 => "x.",2 => "xx",3 => "x."},
  115 => #{1 => ".x",2 => "x.",3 => "x."},
  116 => #{1 => ".x",2 => "xx",3 => "x."},
  117 => #{1 => "x.",2 => "..",3 => "xx"},
  118 => #{1 => "x.",2 => "x.",3 => "xx"},
  119 => #{1 => ".x",2 => "xx",3 => ".x"},
  120 => #{1 => "xx",2 => "..",3 => "xx"},
  121 => #{1 => "xx",2 => ".x",3 => "xx"},
  122 => #{1 => "x.",2 => ".x",3 => "xx"}}

Braille = 
#{{"..","..",".."} => 32,
  {".x","x.",".."} => 105,
  {".x","x.","x."} => 115,
  {".x","xx",".."} => 106,
  {".x","xx",".x"} => 119,
  {".x","xx","x."} => 116,
  {"x.","..",".."} => 97,
  {"x.","..","x."} => 107,
  {"x.","..","xx"} => 117,
  {"x.",".x",".."} => 101,
  {"x.",".x","x."} => 111,
  {"x.",".x","xx"} => 122,
  {"x.","x.",".."} => 98,
  {"x.","x.","x."} => 108,
  {"x.","x.","xx"} => 118,
  {"x.","xx",".."} => 104,
  {"x.","xx","x."} => 114,
  {"xx","..",".."} => 99,
  {"xx","..","x."} => 109,
  {"xx","..","xx"} => 120,
  {"xx",".x",".."} => 100,
  {"xx",".x","x."} => 110,
  {"xx",".x","xx"} => 121,
  {"xx","x.",".."} => 102,
  {"xx","x.","x."} => 112,
  {"xx","xx",".."} => 103,
  {"xx","xx","x."} => 113}
ok
3> braille:test("the quick brown fox jumps over the lazy dog").
.xx.x...xxx..xxxx...x.x.x..xxx..xxx.xx...xx.xxxx.x..x.x.x.x....xx.x...x.x.x.xx..xxx.xx
xxxx.x..xx..x.......x.xx.xxx.x..x..x....xx....x.x....xx..xxx..xxxx.x..x....x.x...x.xxx
x.......x.xx....x.....x.x..xx.....x.xx....xxx.x.x...x.xx..x...x.......x...xxxx....x...
the quick brown fox jumps over the lazy dog
ok
4>