bob*_*bob 1 erlang foreach list
我想创建一个新列表,其中只包含长度为1的"列表列表"的元素.
我提供的代码给出了一个异常错误:没有函数子句匹配.
lists:foreach(fun(X) if length(X) =:= 1 -> [X] end, ListOfLists).
Run Code Online (Sandbox Code Playgroud)
我是erlang的新手,我很难找到另一种编写这段代码的方法.
有人可以就如何这样做给我一些建议吗?
你可以在列表理解中匹配以获得这个很自然:
[L || L = [_] <- ListOfLists]
Run Code Online (Sandbox Code Playgroud)
例如:
1> LoL = [[a], [b,c], d, [e], [f,g]].
[[a],[b,c],d,[e],[f,g]]
2> [L || L = [_] <- LoL].
[[a],[e]]
Run Code Online (Sandbox Code Playgroud)
如果你想要元素本身(如结果[a, e]而不是[[a], [e]]),你可以匹配形状中的元素:
3> [L || [L] <- LoL].
[a,e]
Run Code Online (Sandbox Code Playgroud)
根据其中包含的列表的大小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).
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为foreach/2只返回ok,从不返回任何值.仅当您想要遍历列表以获得副作用时才使用它,而不是因为您想要获得返回值.例如,如果我有聊天系统,聊天室会有一个当前成员列表,并且广播消息实际上是将每条聊天消息发送给列表中的每个成员,我可能会这样做:
-spec broadcast(list(), unicode:chardata()) -> ok.
broadcast(Users, Message) ->
Forward = fun(User) -> send(User, Message) end,
lists:foreach(Forward, Users).
Run Code Online (Sandbox Code Playgroud)
我不关心返回值,真的,我们没有改变列表中的任何内容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]]
Run Code Online (Sandbox Code Playgroud)
细分如下:
Single =
fun
(X, A) when length(X) =:= 1 -> [X|A];
(_, A) -> [X|A]
end,
ListOfSingles = lists:foldl(Single, [], LoL).
Run Code Online (Sandbox Code Playgroud)
这是一个具有两个子句的匿名函数.
用我们可以做的案例写另一种方式:
Single =
fun(X, A) ->
case length(X) of
1 -> [X|A];
_ -> A
end
end,
Run Code Online (Sandbox Code Playgroud)
这是一个偏好的问题,因为选择内联作为调用中的匿名函数foldl/3.
但是,你真正想要做的是过滤列表,并且有一个通用列表函数.你提供了一个返回布尔值的测试函数 - 如果测试为真,那么元素将在输出中出现,否则它将不会:
5> lists:filter(fun([X]) -> true; (_) -> false end, LoL).
[[a],[e]]
Run Code Online (Sandbox Code Playgroud)
像以前一样打破lambda:
6> Single =
6> fun([X]) -> true;
6> (_) -> false
6> end.
#Fun<erl_eval.6.54118792>
7> lists:filter(Single, LoL).
[[a],[e]]
Run Code Online (Sandbox Code Playgroud)
这里我们匹配匿名函数头中元素的形状.这个过滤器几乎完全等同于上面的列表推导(唯一的区别,实际上,在列表推导的底层实现中 - 在语义上它们是相同的).
| 归档时间: |
|
| 查看次数: |
1604 次 |
| 最近记录: |