2010-11-22 25 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).