我有一个代码,该代码重复生成所有可能的变化(以N的宽度为单位)。
variation(1, L) ->
[ [H] || H <- L ];
variation(N, L) ->
[[H | T] || H <- L, T <- variation(N - 1, L)].
对于变化(3,[1,2,3,4]),它将生成:
[[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,1,4],[1,1,2 ,1],...]
我想在列表生成过程中检查条件。如果子列表失败,则应停止生成以特定子列表开头的列表。 例如,如果[1,1]子列表不满足该条件(检查),则它不应生成[1,1,1,1],[1,1,1,2]等(所有以[1 ,1])。
我不知道是否可以通过1个列表理解来实现。 到目前为止,我有以下代码:
variation(1, L) ->
[ [H] || H <- L ];
variation(N, L) ->
[[H | T] || H <- L, T <- variation(N - 1, L), check([H|T]) ].
此解决方案将仅返回不会失败条件的列表(它可以工作,但对于大输入而言确实很慢)。
如果[1,1]失败,它将尝试生成[1,1,1,2],但是那些也将通过检查。我需要一个解决方案,该解决方案不要尝试生成以[1,1,...](或先前失败的子列表)开头的列表。
答案 0 :(得分:1)
首先有一个小细节:根据您的问题,variations(3, [1,2,3]).
应该生成[[1,1,1,1], [1,1,1,2], …]
,但实际上它会生成[[1,1,1], [1,1,2], …]
。我会假设代码是正确的,而您的意思是说variations(4, [1,2,3]).
应该生成[[1,1,1,1], [1,1,1,2], …]
我编写了函数的替代版本,在LC的右侧使用了不同的顺序,避免了在用check/1
检查时其前缀已经为false时生成列表:
variation(1, L) ->
[ [Elem] || Elem <- L ];
variation(N, L) ->
[ Init ++ [Last] || Init <- variation(N-1, L), check(Init), Last <- L].
如您所见,由于check(Init)
发生在之前 Last <- L
,因此Last
仅在check(Init) == true
时生成。
这可能会产生您想要的效果。
但是……要小心。我在LC的左侧使用了++
。您绝对应该对您的代码进行基准测试,看看是否对性能有影响。
如果确实如此,并且并且只有这样,您可能要考虑使用类似这样的东西:
variation3(1, L) ->
[ [Elem] || Elem <- L ];
variation3(N, L) ->
[ lists:reverse([Last|lists:reverse(Init)]) || Init <- variation2(N-1, L), check(Init), Last <- L].
也许值得,也许不值得……您需要对自己的东西进行基准测试以弄清这一点。