【问题标题】:list comprehensions plus pattern matching列表推导加模式匹配
【发布时间】:2018-10-30 02:10:20
【问题描述】:

我要解决的问题是:“查找列表 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

【问题讨论】:

    标签: erlang pattern-matching list-comprehension


    【解决方案1】:

    您可以使用列表尾部删除的最后一个元素压缩列表,然后使用列表推导:

    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]
    

    【讨论】:

    • 谢谢!第一个虽然效率低下,但确实展示了如何做我想做的事 - 但不是尝试一个无法工作的深奥生成器,而是你做 2 个简单的生成器
    猜你喜欢
    • 2015-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多