首页 > Erlang快速入门 > 3.11 Erlang快速入门之进一步讨论列表
2013
11-01

3.11 Erlang快速入门之进一步讨论列表

Erlang进一步讨论列表
记得“|”操作符在获取列表头部的作用吗?

50> [M1|T1] = [paris, london, rome].
[paris,london,rome]
51> M1.
paris
52> T1.
[london,rome]

“|”操作符也可以用来为列表增加一个头元素:

53> L1 = [madrid | T1].
[madrid,london,rome]
54> L1.
[madrid,london,rome]

下面我们尝试将列表进行翻转操作:

-module(tut8).
-export([reverse/1]).

reverse(List) ->
	reverse(List, []).

reverse([Head | Rest], Reversed_List) ->
	reverse(Rest, [Head | Reversed_List]);
reverse([], Reversed_List) ->
	Reversed_List.

下载代码
编译并运行:

38> c(tut8).
{ok,tut8}
39> tut8:reverse([1,2,4,3]).
[3,4,2,1]
40> 

考虑Reversed_List是如何被构造出来的。首先是从一个空列表[]开始,我们首先获取现有列表的头元素,放入Reversed_List中,具体过程显示如下:
reverse([1|2,3], []) =>
reverse([2,3], [1|[]])
reverse([2|3], [1]) =>
reverse([3], [2|[1])
reverse([3|[]], [2,1]) =>
reverse([], [3|[2,1]])
reverse([], [3,2,1]) =>
[3,2,1]

模块lists包含了很多对列表进行操作的函数,例如翻转列表,在我们自己动手写一个函数之前,最好还是首先检查一下有没有在模块中已经为我们准备好的函数。
现在我们会过头来看看城市和温度的问题,但是这次将更加结构化一点。首先让我们把整个列表转化为摄氏度表示,并且测试下面的函数:

-module(tut7).
-export([format_temps/1]).
format_temps(List_of_cities) ->
    convert_list_to_c(List_of_cities).
convert_list_to_c([{Name, {f, F}} | Rest]) ->
    Converted_City = {Name, {c, (F -32)* 5 / 9}},
    [Converted_City | convert_list_to_c(Rest)];              
convert_list_to_c([City | Rest]) ->
    [City | convert_list_to_c(Rest)];
convert_list_to_c([]) ->
    [].

编译并运行:

58> c(tut7).
{ok, tut7}.
59> tut7:format_temps([{moscow, {c, -10}}, {cape_town, {f, 70}},
 {stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).
[{moscow,{c,-10}},
 {cape_town,{c,21.1111}},
 {stockholm,{c,-4}},
 {paris,{c,-2.22222}},
 {london,{c,2.22222}}] 

我们一点一点的看:
format_temps(List_of_cities) ->
convert_list_to_c(List_of_cities).

这里我们看到format_temps/1调用了convert_list_to_c/1。convert_list_to_c/1获得列表List_of_cities的头元素,如果需要的话就进行摄氏度的转换。“|”操作符被用来添加转化后的元素到已转化的列表部分。
[Converted_City | convert_list_to_c(Rest)];
或者
[City | convert_list_to_c(Rest)];
我们继续这样的操作直到获取了列表中的最后一个元素(也就是到列表为空)
convert_list_to_c([]) ->
[].
现在我们就完成了对列表的转换工作,我们添加一个函数并且输出它:

-module(tut7).
-export([format_temps/1]).
format_temps(List_of_cities) ->
    Converted_List = convert_list_to_c(List_of_cities),
    print_temp(Converted_List).
convert_list_to_c([{Name, {f, F}} | Rest]) ->
    Converted_City = {Name, {c, (F -32)* 5 / 9}},
    [Converted_City | convert_list_to_c(Rest)];              
convert_list_to_c([City | Rest]) ->
    [City | convert_list_to_c(Rest)];
convert_list_to_c([]) ->
    [].
print_temp([{Name, {c, Temp}} | Rest]) ->
    io:format("~-15w ~w c~n", [Name, Temp]),
    print_temp(Rest);
print_temp([]) ->
    ok.
60> c(tut7).
{ok,tut7}
61> tut7:format_temps([{moscow, {c, -10}}, {cape_town, {f, 70}},
 {stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).
moscow          -10 c
cape_town       21.1111 c
stockholm       -4 c
paris           -2.22222 c
london          2.22222 c
ok 

我们现在已经添加了一个函数去寻找有最高气温和最低气温的城市了。这个程序并不是最有效率的,我们4次遍历整个列表,但是对于清晰程度和正确性来说却没有太大的影响,我们只在确实需要优化性能的时候进行优化:

-module(tut7).
-export([format_temps/1]).
format_temps(List_of_cities) ->
    Converted_List = convert_list_to_c(List_of_cities),
    print_temp(Converted_List),
    {Max_city, Min_city} = find_max_and_min(Converted_List),
    print_max_and_min(Max_city, Min_city).
convert_list_to_c([{Name, {f, Temp}} | Rest]) ->
    Converted_City = {Name, {c, (Temp -32)* 5 / 9}},
    [Converted_City | convert_list_to_c(Rest)];              
convert_list_to_c([City | Rest]) ->
    [City | convert_list_to_c(Rest)];
convert_list_to_c([]) ->
    [].
print_temp([{Name, {c, Temp}} | Rest]) ->
    io:format("~-15w ~w c~n", [Name, Temp]),
    print_temp(Rest);
print_temp([]) ->
    ok.
find_max_and_min([City | Rest]) ->
    find_max_and_min(Rest, City, City).
find_max_and_min([{Name, {c, Temp}} | Rest], 
         {Max_Name, {c, Max_Temp}}, 
         {Min_Name, {c, Min_Temp}}) ->
    if 
        Temp > Max_Temp ->
            Max_City = {Name, {c, Temp}};           % Change
        true -> 
            Max_City = {Max_Name, {c, Max_Temp}} % Unchanged
    end,
    if
         Temp < Min_Temp ->
            Min_City = {Name, {c, Temp}};           % Change
        true -> 
            Min_City = {Min_Name, {c, Min_Temp}} % Unchanged
    end,
    find_max_and_min(Rest, Max_City, Min_City);

find_max_and_min([], Max_City, Min_City) ->
    {Max_City, Min_City}.
print_max_and_min({Max_name, {c, Max_temp}}, {Min_name, {c, Min_temp}}) ->
    io:format("Max temperature was ~w c in ~w~n", [Max_temp, Max_name]),
    io:format("Min temperature was ~w c in ~w~n", [Min_temp, Min_name]).  
62> c(tut7).
{ok, tut7}
63> tut7:format_temps([{moscow, {c, -10}}, {cape_town, {f, 70}},
 {stockholm, {c, -4}}, {paris, {f, 28}}, {london, {f, 36}}]).
moscow          -10 c
cape_town       21.1111 c
stockholm       -4 c
paris           -2.22222 c
london          2.22222 c
Max temperature was 21.1111 c in cape_town
Min temperature was -10 c in moscow
ok

留下一个回复

你的email不会被公开。