Erlang Central

Difference between revisions of "Spliting a List"

From ErlangCentral Wiki

(Problem)
Line 1:Line 1:
 
== Problem ==
 
== Problem ==
  
Splitting a list in two lists whose lengths are half of the original.  
+
Splitting a list into two lists whose lengths are half of the original.
  
 
== Solution ==
 
== Solution ==

Revision as of 06:45, 9 March 2007

Problem

Splitting a list into 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]}