Search code examples
listerlang

Flatten a list of nested lists in Erlang


I'm working on the exercises in Erlang Programming.

The question is

Write a function that, given a list of nested lists, will return a flat list.

Example: flatten([[1,[2,[3],[]]], [[[4]]], [5,6]]) ⇒ [1,2,3,4,5,6].

Hint: use concatenate to solve flatten.

And here is my concatenate function

%% concatenate([[1,2,3], [], [4, five]]) ⇒ [1,2,3,4,five].
concatenate([X|Xs]) -> concat(X, Xs, []).
concat([X|Xs], T, L) -> concat(Xs, T, [X|L]);
concat([], [X|Xs], L) -> concat(X, Xs, L);
concat([], [], L) -> reverse(L).

I really want to know an elegant way to implement flatten. I've spent hours solving this exercise.

UPDATE: I forget most important prerequisite. Is it possible solving this problem with only recursion and pattern matching?


Solution

  • I would try this way

    flatten(X) -> lists:reverse(flatten(X,[])).
    
    flatten([],Acc) -> Acc;
    flatten([H|T],Acc) when is_list(H) -> flatten(T, flatten(H,Acc));
    flatten([H|T],Acc) -> flatten(T,[H|Acc]).
    

    testing

    my:flatten([[1,[2,[3],[]]], [[[4]]], [5,6]]).
    [1,2,3,4,5,6]
    

    UPD: or this way, without guards and reverse, only recursive calls and pattern matching.

    flatten(X)               -> flatten(X,[]).
    
    flatten([],Acc)          -> Acc;
    flatten([[]|T],Acc)      -> flatten(T, Acc);
    flatten([[_|_]=H|T],Acc) -> flatten(T, flatten(H,Acc));
    flatten([H|T],Acc)       -> flatten(T,Acc++[H]) .