Nested for-loops, there has to be a better way to do this

Andy Kilroy <>
Thu Jul 30 02:25:18 CEST 2009


> Is there a better way to do this?  Anyone would like to demonstrate
> it?

Recommend you learn about the lists:foldl and lists:foldr functions.
Whenever
I'm about to perform iterations over lists I always think of using
these.  It
means that all you have to do is think 'What action do I want to
perform in
each iterative step?'; supply this as the function parameter to foldl
(or
foldr, whichever's appropriate).

> The idea was to be able to pass in a
> list [5, 5, 10] (for example) and go through it all like 3 dimensional
> array.

Hmm, I could only figure out what you wanted to do by running your
program.

I've coded a solution below, but bear in mind I've redefined your
problem
somewhat, to keep the solution fairly generic.  Instead of printing to
the
terminal, I've stated that the loop must return a result.

----------------

-module(looper).

-export([loop/3, nestedLooping/3]).

loop(Acc, SideEffect, IntList) ->
    Exploded = explodeElements(IntList),
    nestedLooping(Acc, SideEffect, Exploded).

nestedLooping(Acc, _SideEffect, []) -> Acc;
nestedLooping(Acc, SideEffect, [InnerList | TheRest]) ->
    Func = fun(Elem, Accum) ->
		   SideEffect(Elem, nestedLooping(Accum, SideEffect, TheRest))
	   end,
    lists:foldl(Func, Acc, InnerList).


explodeElements([]) ->
    [];
explodeElements([X | IntList]) ->
    [lists:seq(1, X) | explodeElements(IntList)].

----------------

The clever work's done in the nestedLooping function.

Tests are below, showing you how I use the loop definition above. I've
tried to
format the output list so that it's bit easier to spot how it
corresponds with
the output from your program.

----------------
empty_int_list_does_nothing(_Config) ->
    [] = looper:loop([], fun my_callback/2, []).

two_dimen_iteration(_Config) ->
    [2, 4, 3, 2, 1,
     1, 4, 3, 2, 1] =
	looper:loop([], fun my_callback/2, [2, 4]).

three_dimen_iteration(_Config) ->
    [2, 4, 5, 4, 3, 2, 1,
        3, 5, 4, 3, 2, 1,
        2, 5, 4, 3, 2, 1,
        1, 5, 4, 3, 2, 1,
     1, 4, 5, 4, 3, 2, 1,
        3, 5, 4, 3, 2, 1,
        2, 5, 4, 3, 2, 1,
        1, 5, 4, 3, 2, 1 ] =
	looper:loop([], fun my_callback/2, [2, 4, 5]).

my_callback(Element, Accumulator) ->
    [Element | Accumulator].

----------------

Hope that's helpful,

Andy



More information about the erlang-questions mailing list