Лучший способ преобразовать плоский список в ряд двух кортежей в Erlang?

мишень идеально подходит для этого, но это также сделает задание

ls -lr / > output | cat output
5
задан 27 July 2009 в 03:06
поделиться

3 ответа

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

tuples_from_flat_list([], Result) -> lists:reverse(Result).
tuples_from_flat_list([X, Y|T], Acc) -> tuples_from_flat_list(T, [{X, Y}|Acc]).

Это лучший и самый быстрый способ.

3
ответ дан 18 December 2019 в 11:59
поделиться

Самый короткий и лаконичный подход:

pair_up([A, B | Tail]) ->
    [{A,B} | pair_up(Tail)];
pair_up([]) ->
    [].

Или более длинная версия с аккумулятором, но все еще очень идиоматический Erlang:

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

pair_up([A, B | Tail], Acc) ->
    pair_up(Tail, [{A,B} | Acc]);
pair_up([], Acc) ->
    lists:reverse(Acc).

См. Этот раздел в руководстве по эффективности Erlang «Миф: хвостовые рекурсивные функции НАМНОГО быстрее, чем рекурсивные функции» .

Как вы заметите, оба подхода приведут к выходу «badarg» при вызове со списком неравной длины. Это, вероятно, желательно с точки зрения отказоустойчивости.

Также прочтите «Миф: '++' всегда плохо» , чтобы понять, почему мы создаем аккумулятор в обратном порядке только для того, чтобы полностью изменить его, когда это будет сделано, вместо добавления в конец списка.

10
ответ дан 18 December 2019 в 11:59
поделиться

Эта версия более эффективна, чем «прямой» подход с объединением списков, предложенный ранее:

combine(L) when length(L) rem 2 == 0 -> combine([], L).
combine(Acc, []) -> lists:reverse(Acc);
combine(Acc, [H1,H2|T])  -> combine([{H1, H2}|Acc], T).

Для эталонного теста:

comb.erl

-module(combine).
-export([reverse/1, straight/1, test/2]).

test(F, L) -> {Micros, _} = timer:tc(?MODULE, F, [L]), Micros.

reverse(L) when length(L) rem 2 == 0 -> reverse([], L).                                  
straight(L) when length(L) rem 2 == 0 -> straight([], L).

reverse(Acc, []) -> lists:reverse(Acc);
reverse(Acc, [H1, H2 | T]) -> reverse([{H1, H2} | Acc], T).

straight(Acc, []) -> Acc;
straight(Acc, [H1, H2 | T]) -> straight(Acc ++ [{H1, H2}], T).

вывод:

130> combine:test(reverse, lists:seq(1,1000)).
34
131> combine:test(straight, lists:seq(1,1000)).
1772
2
ответ дан 18 December 2019 в 11:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: