2014-11-24 45 views
2

什么是二郎神等同于以下Python代码:遍历在二郎山笛卡尔积而不生成列表第一

for x in range(9): 
    for y in range(9): 
     for z in range(9): 
      foo(x, y, z) 

我知道我可以C = [{X,Y,Z} || X<- lists:seq(1,9), Y<- lists:seq(1,9), Z<- lists:seq(1,9)]然后foo([])->done; foo([H|T])->blah blah.

如何先做生成产品我没有一个辅助列表,只使用递归?

回答

1

你可以用三个递归函数来做到这一点。

您可能可以通过函数头中的某些复杂模式匹配来完成此操作。跳过辅助列表的创建

但最简单的方法就是

C = [foo(X, Y, Z) || X<- lists:seq(1,9), 
        Y<- lists:seq(1,9), 
        Z<- lists:seq(1,9)] 

foo/3过程中的一个元素通话清单里面理解你的函数。

0

列表理解仍然强制您在内存中创建辅助列表。 如果处理大量的数据集,你应该避免它。每次写递归函数也很尴尬,所以我想出了自己的泛型函数。遍历的速度比直接递归或列表理解慢一点,但内存稳定,通用且易于使用。

用法:

(for({10}))(
    fun (X) -> io:format("~p ",[X]) end). 
> 1 2 3 4 5 6 7 8 9 10 

(for({10, -10, -2}))(
    fun (X) -> io:format("~p ",[X]) end). 
> 10 8 6 4 2 0 -2 -4 -6 -8 -10 

与列表过于作品:

(for(lists:seq(10, -10, -2)))(
    fun (X) -> io:format("~p ",[X]) end). 
> 10 8 6 4 2 0 -2 -4 -6 -8 -10 

它也可以定义步或保护的功能:如果你传递给了

(for({256, 1.1, fun (X) -> math:sqrt(X) end, fun (X, Range) -> X > Range end}))(
    fun (X) -> io:format("~p ",[X]) end). 
> 256 16.0 4.0 2.0 1.4142135623730951 1.189207115002721 

两个参数函数,那么您可以像使用列表一样使用累加器功能:foldl/3。您还需要将初始累加器传递给:

Fact = (for(1, {1, 5}))(
    fun(X, Acc) -> 
     X * Acc 
    end), 
io:format("~p", [Fact]). 
> 120 

e_fact(N) -> 
    {_, E} = (for({1, 1}, {1, N}))(% i assumed 1/0! equals 1 
    fun(X, {LastFact, Sum}) -> 
     Fact = LastFact * X, 
     {Fact, Sum + 1/Fact} 
    end), 
    E. 
io:format("e=~p", [e_fact(10)]). 
> e=2.7182818011463845 

此外,步进和保护功能可以取决于累加器。只需传递一个参数即可。

嵌套循环寻找毕达哥拉斯三元组。容易与关闭:

pyth_lists(N) -> 
    [io:format("~p ", [{A, B, C}]) || 
    A <- lists:seq(1, N), 
    B <- lists:seq(A + 1, N), 
    C <- lists:seq(B + 1, N), 
    A * A + B * B == C * C]. 

pyth_for(N) -> 
    (for({1, N}))(
    fun(A) -> 
     (for({A + 1, N}))(
     fun(B) -> 
      (for({B + 1, N}))(
      fun(C) -> 
       case A * A + B * B == C * C of 
       true -> io:format("~p ", [{A, B, C}]); 
       false -> ok 
       end 
      end) 
     end) 
    end). 

这对于外部存储库来说太小了。我把它放在我的公用程序模块中。 如果您觉得它有帮助,这里是代码:

-export([for/1, for/2]). 

for(Through) -> 
    for([], Through). 

for(InitAcc, Opts) when is_tuple(Opts) -> 
    {Init, Range, Step, Guard} = for_apply_default_opts(Opts), 
    fun(Fun) -> 
    UpdFun = if 
     is_function(Fun, 1) -> 
     fun(I, _FAcc) -> Fun(I) end; 
     is_function(Fun, 2) -> 
     Fun 
    end, 
    for_iter(UpdFun, InitAcc, Init, Range, Step, Guard) end; 

for(InitAcc, List) when is_list(List) -> 
    fun(Fun) -> for_list_eval(Fun, InitAcc, List) end. 

for_iter(Fun, Acc, I, Range, Step, Guard) -> 
    case Guard(I, Range, Acc) of 
    false -> 
     Acc; 
    true -> 
     NewAcc = Fun(I, Acc), 
     for_iter(Fun, NewAcc, Step(I, NewAcc), Range, Step, Guard) 
    end. 

for_list_eval(Fun, Acc, List) -> 
    if 
    is_function(Fun, 1) -> 
     lists:foreach(Fun, List); 
    is_function(Fun, 2) -> 
     lists:foldl(Fun, Acc, List) 
    end. 

for_apply_default_opts({Range}) -> 
    DefaultInit = 1, 
    for_apply_default_opts({DefaultInit, Range}); 

for_apply_default_opts({Init, Range}) -> 
    DefaultStep = 1, 
    for_apply_default_opts({Init, Range, DefaultStep}); 

for_apply_default_opts({Init, Range, Step}) -> 
    DefaultGuard = case (Step > 0) or is_function(Step) of 
        true -> fun(I, IterRange, _Acc) -> I =< IterRange end; 
        false -> fun(I, IterRange, _Acc) -> I >= IterRange end 
       end, 
    for_apply_default_opts({Init, Range, Step, DefaultGuard}); 

for_apply_default_opts({Init, Range, Step, Guard}) when is_function(Guard, 2) -> 
    for_apply_default_opts({Init, Range, Step, fun(I, IterRange, _Acc) -> Guard(I, IterRange) end}); 

for_apply_default_opts({Init, Range, Step, DefaultGuard}) when is_number(Step) -> 
    for_apply_default_opts({Init, Range, fun(I, _Acc) -> I + Step end, DefaultGuard}); 

for_apply_default_opts({Init, Range, Step, DefaultGuard}) when is_function(Step, 1) -> 
    for_apply_default_opts({Init, Range, fun(I, _Acc) -> Step(I) end, DefaultGuard}); 

for_apply_default_opts({_Init, _Range, _Step, _DefaultGuard} = Opts) -> 
    Opts.