我知道你已经得到了答案,但我昨天去海滩之前读了你的问题,我在看风筝冲浪“芭蕾舞”时想象了这个问题,所以我给了它,它和史蒂夫的有点不同,所以可能很有趣。
在此分析的情况下不能使用 lists:map 函数,因为它仅将给定函数应用于列表的每个元素以构建具有相同长度的新列表。没有办法建立嵌套列表。正如@Steve 所说,您需要一个累加器来逐步构建结果。
列表库提供了一个在遍历列表时累积术语的功能:lists:foldl/3(它也存在 foldr、mapfoldl 和 mapfoldr),在这种情况下,问题是定义将帮助我们构建预期结果的累加器。
可以以单一形式满足 2 个需求的最简单结构是列表列表:[SublistInProgress|PreviousWork]
现在我们知道了累加器的形式,我们可以定义负责构建它的函数,3种情况:
- 我们找到一个“(”:开始一个新的子列表,并“存储”之前的累加器
- 我们找到一个“)”:将子列表添加到前一个累加器中
- 任何其他情况将元素添加到正在进行的子列表中。
在外壳中:
1> F = fun("(",Acc)-> [[],Acc];
1> (")",[SubList,[Hacc|Tacc]]) -> [[lists:reverse(SubList)|Hacc]|Tacc];
1> (X,[Hacc|Tacc]) -> [[X|Hacc]|Tacc] end.
#Fun<erl_eval.12.52032458>
注意:我使用构造[X|Hacc]
而不是在列表中累积元素Hacc ++ [X]
,这是一个好习惯,因为它避免在每一步都创建一个全新的列表(这样做我会避免我的朋友@Hynek-Pichi-Vychodil 的评论:o)。所以当我想存储它时,我必须反转列表。
在函数中使用 Flists:foldl(F,[[]],L)
我们将得到一个元素的列表,该元素与预期结果相反。所以我们必须将这个对库的调用嵌入到一个特定的函数中:
2> Transform = fun(L) -> [R] = lists:foldl(F,[[]],L),
2> lists:reverse(R) end.
#Fun<erl_eval.6.52032458>
我们可以测试它:
3> L1 = ["0", "(", "1", "2", "3", ")"].
["0","(","1","2","3",")"]
4> L2 = ["0", "(", "11", "22", "(", "333", "444","(", "5555", ")", "666", ")", "77", "88", ")", "9"].
["0","(","11","22","(","333","444","(","5555",")","666",")",
"77","88",")","9"]
5> Transform(L1).
["0",["1","2","3"]]
6> Transform(L2).
["0",["11","22",["333","444",["5555"],"666"],"77","88"],"9"]