将从文件中读取的行拆分为 Erlang 中的键值对数组

Splitting lines read from file into array of key-value pairs in Erlang

我有一个包含 N 个键值对的 txt 文件:

key_1=val_1
key_2=val_2
key_N=val_N

我需要读取此文件并将其设置为一个数组:

Attributes = [
    {key_1, val_1},
    {key_2, val_2},
    {key_N, val_N}],

我尝试了几种不同的方法,但 none 成功了,我得到的最接近的方法如下:

{ok, FileAttributes} = file:read_file("/data/file-attributes.txt"),
string:split(FileAttributes, "=", all)

但是当我打印这个时我得到:

key_1val_1
key_2val_2
key_Nval_N

读取 file-attributes.txt 并将键和值拆分为属性数组的项目的最佳方法是什么?

I have a txt file with N key-value pairs:

key_1=val_1
key_2=val_2
key_N=val_N

I need to read this file and set those to an array:

Attributes = [
    {key_1, val_1},
    {key_2, val_2},
    {key_N, val_N}],
make_array(FileName) ->
    case file:read_file(FileName) of
        {ok, Bin} ->
            Lines = binary:split(Bin, <<"\n">>, [trim, global]),
            Array = make_tuples(Lines, []),
            io:format("Result=~n~p~n", [Array]);
        {error, Reason} ->
            io:format("[Me] There was an error:~n~w", [Reason])
    end.

make_tuples([Line|Lines], Acc) ->
    io:format("Line= -->~s<--~n", [Line]),
    [Left, Right] = binary:split(Line, <<"=">>),
    io:format("Term={~s, ~s}~n", [Left, Right]),
    make_tuples(Lines, [{Left, Right}|Acc]);
make_tuples([], Acc) -> lists:reverse(Acc).

--输出:--

58> c(a).                               
a.erl:2:2: Warning: export_all flag enabled - all functions will be exported
%    2| -compile(export_all).
%     |  ^

{ok,a}

59> a:make_array("file-attributes.txt").
Line= -->key_1=val_1<--
Term={key_1, val_1}
Line= -->key_2=val_2<--
Term={key_2, val_2}
Line= -->key_N=val_N<--
Term={key_N, val_N}
Result=
[{<<"key_1">>,<<"val_1">>},
 {<<"key_2">>,<<"val_2">>},
 {<<"key_N">>,<<"val_N">>}]
ok

匹配示例:

-module(a).
-compile(export_all).

go([{1, Y, Z}=Tuple | Tuples]) ->
    io:format("~w -> 2nd + 3rd = ~w~n", [Tuple, Y+Z]),
    go(Tuples);
go([{X, 2, Z}=Tuple | Tuples]) ->
    io:format("~w -> 1st + 3rd = ~w~n", [Tuple, X+Z]),
    go(Tuples);
go([{X, Y, 3}=Tuple | Tuples]) ->
    io:format("~w -> 1st + 2nd = ~w~n", [Tuple, X+Y]),
    go(Tuples);
go([{X, Y, Z}=Tuple | Tuples]) ->
    io:format("~w -> Sum = ~w~n", [Tuple, X+Y+Z]),
    go(Tuples);
go([]) -> all_done.

test() ->
    go([
        {1, 2, 3},
        {3, 2, 1},
        {3, 4, 3},
        {10, 20, 30}
       ]).

--输出:--

14> c(a).    
a.erl:2:2: Warning: export_all flag enabled - all functions will be exported
%    2| -compile(export_all).
%     |  ^

{ok,a}

15> a:test().
{1,2,3} -> 2nd + 3rd = 5
{3,2,1} -> 1st + 3rd = 4
{3,4,3} -> 1st + 2nd = 7
{10,20,30} -> Sum = 60
all_done

只有一个元素的列表可以写成:

[ 4 | [] ]

因此,如果您有以下函数子句:

go( [Head|Tail] ) -> 
    %% do stuff with Head
    go(Tail).

并调用:

g([4]).

erlang 会将 4 分配给 Head 并将空列表 [] 分配给 Tail。但是,当 Tail 为空列表时,对 go(Tail) 的调用将无法匹配该函数子句,从而导致程序崩溃。

此外,请注意,与 Java 不同,函数头可以混合使用常量和变量作为参数。