我试图解决的问题是:“找到列表L的所有元素,后面跟着值为X的元素。”
我试图使用列表理解来做到这一点。但是,我现在怀疑它是否可能。我理解事情应该在一个更简单的场景中工作,比如这个
[some_transformation(X) || X <- [...], some_conditional(X)].
Xs上有一个过滤器,它来自Xs的生成器,并且转换应用于那些通过的过滤器。
我的希望非常渺茫,因为Erlang的模式匹配能力允许这样的事情:
[H1|[H2|T]] = [1,2,3,4].
,它绑定H1和H2。是否有一些模式可以在列表理解中使用以实现所需的结果?
当我天真地尝试这个时,它显然不起作用:
78> [X||[H1|[H2|_]]=X <- [1,2,3,4]].
[]
也许我应该停止懒惰,并希望列表理解和模式匹配的魔力为我做所有的工作? = P
答案 0 :(得分:3)
您可以使用列表尾部删除的最后一个元素压缩列表,然后使用list comprehension:
1> List = [1, 2, 3, 2, 1, 2, 2, 1, 1, 3, 1].
[1,2,3,2,1,2,2,1,1,3,1]
2> X = 1.
1
3> Zipped = lists:zip(lists:droplast(List), tl(List)).
[{1,2},
{2,3},
{3,2},
{2,1},
{1,2},
{2,2},
{2,1},
{1,1},
{1,3},
{3,1}]
4> [A || {A, B} <- Zipped, B == X].
[2,2,1,3]
这样效率很低 - 它会创建列表的副本(对于droplast
)和新的压缩列表。您可以使用这样的递归来提高效率:
-module(a).
-export([before/2]).
before(List, X) ->
before(List, X, []).
before([A, X | Tail], X, Acc) ->
before([X | Tail], X, [A | Acc]);
before([_ | Tail], X, Acc) ->
before(Tail, X, Acc);
before([], _, Acc) ->
lists:reverse(Acc).
1> c(a).
{ok,a}
2> a:before([1, 2, 3, 2, 1, 2, 2, 1, 1, 3, 1], 1).
[2,2,1,3]