如果子列表检查失败,列表理解将停止生成某些列表
List comprehension stop generating certain lists if sublist fails on check
我有一个代码,可以生成所有可能的变化(长度为 N)并重复。
variation(1, L) ->
[ [H] || H <- L ];
variation(N, L) ->
[[H | T] || H <- L, T <- variation(N - 1, L)].
对于 variation(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]) ].
此解决方案只会 return 那些不满足条件的列表(它有效,但对于大输入来说真的很慢)。
如果 [1,1] 失败,它将尝试生成 [1,1,1,2],但这些也将无法通过检查。我需要一个解决方案,它不会尝试生成以 [1,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
:
检查前缀已经为假时生成列表
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].
也许值得,也许不……你需要对你的东西进行基准测试才能弄明白。
我有一个代码,可以生成所有可能的变化(长度为 N)并重复。
variation(1, L) ->
[ [H] || H <- L ];
variation(N, L) ->
[[H | T] || H <- L, T <- variation(N - 1, L)].
对于 variation(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]) ].
此解决方案只会 return 那些不满足条件的列表(它有效,但对于大输入来说真的很慢)。
如果 [1,1] 失败,它将尝试生成 [1,1,1,2],但这些也将无法通过检查。我需要一个解决方案,它不会尝试生成以 [1,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
:
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].
也许值得,也许不……你需要对你的东西进行基准测试才能弄明白。