Erlang Central

Spliting a List

From ErlangCentral Wiki


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


Use the lists:split function.

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

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),
        Y == [] -> { lists:reverse([hd(Slow) | Front]), tl(Slow) };
        true    -> sih_loop( [hd(Slow) | Front],
                             tl(Slow), tl(tl(Fast)))

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

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