Erlang Central

Difference between revisions of "Spliting a List"

From ErlangCentral Wiki

 
Line 42:Line 42:
 
{[1,2,3],[4,5,6]}
 
{[1,2,3],[4,5,6]}
 
</code>
 
</code>
[[Category:CookBook]]
+
[[Category:CookBook]][[Category:ListRecipes]]

Revision as of 22:44, 3 September 2006

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]}