Erlang Central

Spliting a List

Revision as of 02:39, 31 August 2006 by Cyberlync (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Problem

Splitting a list in two lists whose lengths are half of the original.

Solution

Use the lists:split function.

1> List = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16].
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2> lists:split(length(List) div 2, List).
{[1,2,3,4,5,6,7,8],[9,10,11,12,13,14,15,16]}
3> List2 = [1,2,3,4,5,6,7].
[1,2,3,4,5,6,7]
4> lists:split(length(List2) div 2, List2).
{[1,2,3],[4,5,6,7]}

Note the use of integer division by the div function to provide proper input to the function. Also note that the split function will work properly on lists that can't be split into two equal lengths.

The obvious lists:split solution works, but is not optimal, because it traverses the list two times (once to get the length of the list, and another time to find the element at which to break the list).

We can provide a better solution by

% split_in_halves : list -> {list,list}
%  return two lists of lengths differing with at most one
sih_loop(Front, Slow, []) -> {lists:reverse(Front), Slow};
sih_loop(Front, Slow, Fast) ->
    Y = tl(Fast),
    if
        Y == [] -> { lists:reverse([hd(Slow) | Front]), tl(Slow) };
        true    -> sih_loop( [hd(Slow) | Front],
                             tl(Slow), tl(tl(Fast)))
    end.

split_in_halves(List) ->
    sih_loop([], List, List).

5> split_in_halves([1,2,3,4,5]).
{[1,2,3],[4,5]}
6> split_in_halves([1,2,3,4,5,6]).
{[1,2,3],[4,5,6]}