2010-11-22 56 views
1

我有一个项目列表,我想“un-zip-flatten”。基本上,这是什么意思是,如果我有一个项目列表:Erlang un-zip-flatten

[a, b, c, d, e, f, g] 

我希望把它变成像下面列出的清单:

[[a, d, g], [b, e], [c, f]] 

到目前为止,我的解决办法是这样的:

unzipflatten(NumberOfLists, List) -> 
    lists:map(fun(Start) -> 
         lists:map(fun(N) -> 
             lists:nth(N, List) 
           end, 
           lists:seq(Start, length(List), NumberOfLists)) 
       end, 
       lists:seq(1, NumberOfLists)). 

我是很新,二郎,所以我想知道如果我错过了一些标准库函数会做我想做的,或者如果有一个更“Erlangish”的方式,或者,如果要做到这一点我上面的表现解决方案会发臭。

回答

2

我认为这将是一个更“Erlangish”的方法来做到这一点。基本上你会创建列表,这将是你的结果,并使用两个列表来管理这些列表,像一个队列。 “头”列表包含您将在下一个前面列出的列表,并且“尾部”列表是最近预先考虑的列表。当头部是空的时候,你只需反转尾巴并将其用作新的头部。在返回结果之前,您需要将尾部和头部中的所有列表反向,然后将头部原样添加到反向尾部。请问混乱的变量名,我想不起来了几个好名字在一个Erlang程序分手清单是最难的部分;)

unzipflatten(NumberOfLists, List) when NumberOfLists > 0 -> 
    unzipflatten(List, lists:duplicate(NumberOfLists, []), []). 

unzipflatten([], Heads, Tails) -> 
    [lists:reverse(L) || L <- lists:reverse(Tails, Heads)]; 
unzipflatten(L, [], Tails) -> 
    unzipflatten(L, lists:reverse(Tails), []); 
unzipflatten([Elem | Rest], [Head | Tail], Tails) -> 
    unzipflatten(Rest, Tail, [[Elem | Head] | Tails]). 

也有可能做了“解压缩”阶段在非tail-递归的方式来避免列表:逆向步骤,但这是一个更复杂的解决方案。类似这样的:

unzipflatten(NumberOfLists, List) when NumberOfLists > 0 -> 
    unzipflatten({List, lists:duplicate(NumberOfLists, [])}). 

unzipflatten({[], Heads}) -> 
    [lists:reverse(L) || L <- Heads]; 
unzipflatten({L, Heads}) -> 
    unzipflatten(unzipper({L, Heads})). 

unzipper({[], Heads}) -> 
    {[], Heads}; 
unzipper({L, []}) -> 
    {L, []}; 
unzipper({[H | T], [Head | Tail]}) -> 
    {T1, Tail1} = unzipper({T, Tail}), 
    {T1, [[H | Head] | Tail1]}. 
0

是的,性能会很差(使用lists:nth时的基本建议:不要多次调用N!)。像这样的东西应该得到更好的(未测试):

unzipflatten(NumberOfLists, List) -> 
    unzipflatten(NumberOfLists, List, array:new(NumberOfLists, {default, []}), 0). 

unzipflatten(_, [], Lists, _) -> 
    lists:map(fun lists:reverse/1, array:to_list(Lists)); 
unzipflatten(NumberOfLists, [H | T], Lists, CurrentIndex) -> 
    NewLists = array:set(CurrentIndex, [H | array:get(CurrentIndex, Lists)], Lists), 
    unzipflatten(NumberOfLists, T, NewLists, (CurrentIndex + 1) rem NumberOfLists).