【发布时间】:2020-08-16 08:06:56
【问题描述】:
我目前正在攻读计算机科学硕士的第二学期,并正在学习分布式系统编程课程。因此,我们应该提交每周练习,其中还包括 Erlang 编码练习。
由于这是课程的第二周,我们才刚刚开始使用 Erlang,这是第一个练习,我们应该在一个模块中实现 6 个函数。前 5 个功能我自己可以轻松完成,但第 6 个功能完全让我不知所措。为此,我们应该编写一个接受 2 个输入的函数:一个表示键值对的元组列表和一个包含要搜索的键的列表。然后该函数应该在整个列表中搜索这些键的所有出现并返回它们。
因为第一个 Erlang 练习是为了让我们熟悉该语言的基本概念,这意味着我们应该通过使用递归而不是 list:max 之类的东西来解决这些任务。
我能够为之前的任务实现一个工作函数,它只是在键值对元组列表中搜索一个键并返回第一个结果。那个实现看起来很容易,但是为了扩展这个任务,我尝试了很多没有用的东西,我什至不知道接下来要尝试什么。
目前我尝试了这种方法:
find_all(Keys, Values) ->
AllFindings = [],
lists:foreach(
fun(Key) ->
lists:foreach(
fun(Value) ->
{X, Y} = Value,
case X == Key of
true -> AllFindings:append(Value);
false -> []
end
end,
Values
)
end,
Keys
),
AllFindings.
这样做的问题是,要么我需要做一些事情,比如将值附加到最初创建的列表中(这给了我这个错误:Warning: invalid module and/or function name; this call will always fail,而且我不确定这是否可能以这种方式我打算让它工作,因为它需要变量 AllFindings 来改变它的值)或者我需要一种方法来保存这些值以供以后使用,这样我就可以在稍后将所有值放在一起时将它们全部输出。
但我不确定如何正确实现这一目标。
我之前尝试实现的方法是这样的,使用递归,但没有按照我想要的方式工作(此版本中的一些值输出仅用于“调试”以查看变量函数处于什么状态的哪个值):
find_all(Keys = [KeyHead | KeyTail], Values = [ValueHead | ValueTail]) ->
Tuples = [X || X = {KeyHead, Y} <- [ValueHead]],
Tuples,
ValueTail,
case Tuples /= [] of
true -> Tuples
end,
case ValueTail /= [] of
true -> find_all(Keys, ValueTail);
false ->
case KeyTail /= [] of
true -> find_all(KeyTail, Values);
false -> find_all(KeyTail, ValueTail)
end
end.
还有:
find_all([], []) -> [];
find_all([KeyHead | KeyTail], [ValueHead | ValueTail]) ->
case ValueHead of
{KeyHead, V} -> V;
{_, V} -> find_all(KeyTail, ValueHead);
_ -> find_all(KeyHead, ValueTail)
end.
我真的很感谢任何关于解决这个问题的建议,无论是通过建议一些代码还是通过将我指向相应的文献,因为对我而言,关于 Erlang 的文献/论坛似乎非常稀少且难以找到(尤其是与流行的语言,如 Java 或 Python)。到目前为止,我还在阅读“Learn You Some Erlang”,但没有遇到任何我认为它可能有助于解决这个问题的特定部分。
编辑
我现在想出了这段代码:
find_all(Keys, Values) ->
while(Keys, Values).
while([], []) -> [];
while(Keys = [KeyHead | KeyTail], Values = [ValueHead | ValueTail]) ->
NumberOfKeys = length(Keys),
LengthOfValues = length(Values),
{K, V} = ValueHead,
erlang:display(Keys), erlang:display(Values),
case NumberOfKeys > 1 of
true -> case LengthOfValues > 1 of
true -> case K =:= KeyHead of
true -> [ValueHead | find_all(Keys, ValueTail)];
false -> [find_all(Keys, ValueTail)]
end;
false -> case K =:= KeyHead of
true -> [ValueHead];
false -> []
end
end;
false -> case LengthOfValues > 1 of
true -> case K =:= KeyHead of
true -> [ValueHead | find_all(Keys, ValueTail)];
false -> [find_all(Keys, ValueTail)]
end;
false -> case K =:= KeyHead of
true -> [ValueHead];
false -> []
end
end
end,
while(KeyTail, Values).
在我看来,它看起来很有希望,因为它的较小版本已经为这个函数调用 warmup:find_all([d, x, c], [{c, 5}, {z, 7}, {d, 3}, {a, 1}]). 返回 {d, 3}。当使用erlang:display() 调试不同的值时,我可以看到它在第一个键上循环了4 次,并且还将ValueTail 减少到最后一个值,然后转到下一个键。但是我很困惑为什么Values 仍然只包含最后一个值{a, 1},因为我认为递归会回到它的调用的顶层,其中列表仍然应该包含所有值?
【问题讨论】:
-
请描述(举例)应该输入什么,应该输出什么以及为什么不能从输入输出
标签: erlang tuples key key-value