当前位置:  开发笔记 > 编程语言 > 正文

每个列表列表的Erlang

如何解决《每个列表列表的Erlang》经验,为你挑选了1个好方法。

我想创建一个新列表,其中只包含长度为1的"列表列表"的元素.

我提供的代码给出了一个异常错误:没有函数子句匹配.

lists:foreach(fun(X) if length(X) =:= 1 -> [X] end, ListOfLists).

我是erlang的新手,我很难找到另一种编写这段代码的方法.

有人可以就如何这样做给我一些建议吗?



1> zxq9..:

你可以在列表理解中匹配以获得这个很自然:

[L || L = [_] <- ListOfLists]

例如:

1> LoL = [[a], [b,c], d, [e], [f,g]].
[[a],[b,c],d,[e],[f,g]]
2> [L || L = [_] <- LoL].
[[a],[e]]

如果你想要元素本身(如结果[a, e]而不是[[a], [e]]),你可以匹配形状中的元素:

3> [L || [L] <- LoL].    
[a,e]

根据其中包含的列表的大小LoL,匹配将比呼叫length/1每个成员快得多.调用length/1然后测试结果需要遍历整个列表,返回一个值,然后对其进行测试.这比检查列表的第二个元素是否是终止(换句话说,如果数据的"形状"匹配)任意更多的开销.

关于你的上述尝试......

作为Erlang的新手,熟悉基本的功能列表操作可能会有所帮助.它们在功能(和逻辑)编程中反复弹出,并且通常具有相同的名称."map","folds","filters","cons","car"("head"或"hd"或[X|_]),"cdr"("tail"或"tl"或[_|X])等等.

你最初的尝试:

lists:foreach(fun(X) if length(X) =:= 1 -> [X] end, ListOfLists).

这不起作用,因为foreach/2只返回ok,从不返回任何值.当您想要遍历列表以获得副作用时才使用它,而不是因为您想要获得返回值.例如,如果我有聊天系统,聊天室会有一个当前成员列表,并且广播消息实际上是将每条聊天消息发送给列表中的每个成员,我可能会这样做:

-spec broadcast(list(), unicode:chardata()) -> ok.
broadcast(Users, Message) ->
    Forward = fun(User) -> send(User, Message) end,
    lists:foreach(Forward, Users).

我不关心返回值,真的,我们没有改变列表中的任何内容Users或者Message.(注意,这里我们使用匿名函数来捕获它所需的相关状态 - 基本上调整了Message值,因此我们可以向列表操作提供arity 1的函数foreach/2.这是lambda在Erlang中最有用的地方vs named功能.)

如果要将列表作为输入并返回单个聚合值(使用某些操作将列表中的所有值都滚动到一个),您可以使用折叠(您几乎总是想要使用foldl/3,特别是):

4> lists:foldl(fun(X, A) when length(X) =:= 1 -> [X|A]; (_, A) -> A end, [], LoL).
[[e],[a]]

细分如下:

Single =
    fun
        (X, A) when length(X) =:= 1 -> [X|A];
        (_, A) -> [X|A]
    end,
ListOfSingles = lists:foldl(Single, [], LoL).

这是一个具有两个子句的匿名函数.

用我们可以做的案例写另一种方式:

Single =
    fun(X, A) ->
        case length(X) of
            1 -> [X|A];
            _ -> A
        end
    end,

这是一个偏好的问题,因为选择内联作为调用中的匿名函数foldl/3.

但是,你真正想要做的是过滤列表,并且有一个通用列表函数.你提供了一个返回布尔值的测试函数 - 如果测试为真,那么元素将在输出中出现,否则它将不会:

5> lists:filter(fun([X]) -> true; (_) -> false end, LoL).
[[a],[e]]

像以前一样打破lambda:

6> Single =
6>     fun([X]) -> true;
6>        (_)   -> false
6>     end.
#Fun
7> lists:filter(Single, LoL).
[[a],[e]]

这里我们匹配匿名函数头中元素的形状.这个过滤器几乎完全等同于上面的列表推导(唯一的区别,实际上,在列表推导的底层实现中 - 在语义上它们是相同的).

推荐阅读
保佑欣疼你的芯疼
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有