尝试在 Erlang 中组合列表的问题
Posted
技术标签:
【中文标题】尝试在 Erlang 中组合列表的问题【英文标题】:Problems trying to combine lists in Erlang 【发布时间】:2011-07-05 13:06:42 【问题描述】:作为学习 Erlang 的练习,我正在尝试编写一个简单的数据库(来自 O'Reilly 的 Programming Erlang)。
基本上我有一个这样的元组列表:
Db1 = [person1,charleston,person2,charleston,person3,chicago].
我需要创建这样的函数
db:match(charleston,Db1).
返回
[person1,person2]
这是我写的方法:
match(Element, Db) -> match(Element, Db, []).
match(_Element,[], Results) -> Results;
match(Element, [Key,Value|T], Results) ->
case Value == Element of
true -> match(Element, T, [Results,Key]);
false -> match(Element,T,Results)
end.
我得到的结果是这样的:
[[[],person1],person2]
我知道有一些方法可以将列表与lists.erl
模块结合起来,但我试图绕过它以了解更多关于该语言的信息。任何想法我做错了什么?
【问题讨论】:
你的case Value == Element
可以折叠成子句:match(Value, [Key, Value|T], ...) ->
等等。
你的情况很简单,我不会在这里使用尾递归累加器,而是使用[Key|match(Element, T)]
作为递归器。
【参考方案1】:
问题在于你是如何建立你的列表的,试试这个:
case Value == Element of
true -> match(Element, T, [Key|Results]);
false -> match(Element,T,Results)
end.
[A,B] 用元素 A 和 B 构建一个新列表。
[A|B] 将 A 添加到列表 B。
【讨论】:
这是原代码的问题。你交换Key
和Results
。
为什么 [Key|Results] 与 [Results|Key] 不同。我认为后一部分附加到第一部分。没有?
Key
是一个值,而 Results
是一个值列表。 [_|_]
构造通常以[Value|ListofValues]
的方式使用,将第一部分添加到第二部分。以相反的顺序使用它是合法的,但这不是处理列表的正常方式,并且不支持这一点。将值附加到列表是另一个效率低得多的操作,如果可能,通常会避免这种操作。
@rvirding 作为副作用然后这实际上会建立一个反向列表,对吗?
@Micah 是的,因为您实际上将元素推送到列表/堆栈,然后您返回。【参考方案2】:
您正在重新发明***。只需使用list comprehension:
match(X, Db) -> [P || P, E <- Db, E == X].
【讨论】:
模式匹配更短:match(X, Db) -> [P || P, X @hdima 该解决方案不起作用,因为 List Comprehensions 生成器中的 X 将隐藏 match/2 参数 X。 我没有将其标记为答案的唯一原因是我还没有对模式匹配做过任何事情,并且正在寻找专门的递归解决方案。但很好的答案。【参考方案3】:另一种直接编写代码的方法是
match(_Value, []) -> [];
match(Value, [Key,Value|T]) ->
[Key|match(Value, T)];
match(Value, [_|T]) ->
match(Value, T).
@Little Bobby Tables 解决方案中的列表推导与此等价。
【讨论】:
看起来你的最后一场比赛/3 不会被调用。所有对 match 的调用都针对 match/2。以上是关于尝试在 Erlang 中组合列表的问题的主要内容,如果未能解决你的问题,请参考以下文章