1

我有一个我想“解压缩”的项目列表。基本上这意味着如果我有一个项目列表:

[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)).

我对 Erlang 很陌生,所以我想知道我是否错过了一些可以满足我要求的标准库函数,或者是否有更“Erlangish”的方式来做到这一点,或者我的上述解决方案的性能是否会臭。

4

2 回答 2

2

我认为这将是一种更“Erlangish”的方法。基本上,您将创建将成为您的结果的列表列表,并使用两个列表来像队列一样管理这些列表。“Heads”列表包含您将添加到下一个的列表,“Tails”列表是最近添加到的列表。当 Heads 为空时,您只需反转 Tails 并将其用作新的 Heads。在返回结果之前,您需要反转 Tails 和 Heads 中的所有列表,然后将 Heads 按原样附加到反转的 Tails 中。请原谅令人困惑的变量名称,我认为在 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]).

也可以以非尾递归方式执行“解压缩”阶段以避免列表:反向步骤,但这是一个更复杂的解决方案。像这样的东西:

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]}.
于 2010-11-23T04:09:43.780 回答
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).
于 2010-11-22T22:20:58.983 回答