返回列表中的最大值

7

我正在尝试返回列表中的最大值。

我有以下代码:

list_max([]) ->
    [];
list_max([H|T]) ->
    list_max(H, T).
list_max(Temp, []) ->
    Temp;
list_max(Temp, [H|T]) when H > Temp ->
    Temp = H;
list_max(Temp, T).

但我很难理解Erlang。

如何将某物赋值给temp并替换为最高值?

5个回答

7

Erlang是我发现更容易展示而不是解释的语言之一。

list_max([]   ) -> empty;
list_max([H|T]) -> {ok, list_max(H, T)}.

list_max(X, []   )            -> X;
list_max(X, [H|T]) when X < H -> list_max(H, T);
list_max(X, [_|T])            -> list_max(X, T).

并将其称为这样:
{ok, Max} = list_max(MyList).

@daniel-luna 的例子是最好的。它实际上是 Erlang 中列表最大值函数 lists:max(L) 的本地实现。为什么它更好呢?请注意迭代顺序。在您的情况下,您将不必要地匹配每次迭代列表末尾的第一个元素。最佳迭代情况在 @daniel-luna 的例子中。 - Grigore Madalin

5
抱歉,也许我漏掉了什么。您是在寻找以下内容吗:
lists:max(List). %% Find the max in List

不,我需要自己做。 :P - some_id
好的!:D 谢谢。现在我能够理解文档了,哈哈哈。 - Adriano Tadao

4
我该如何将某物指定给temp并将其替换为最高值?
简短的回答是你不能。在Erlang中,一旦变量被赋值就不能更改。
稍微详细一点的回答是,虽然你不能在特定函数调用内更改变量,但你总是可以进行自我递归。在Erlang中,尾递归是经过优化的。
在你提供的示例代码中,list_max只会查看列表的前两个元素。第四和第五个子句应该各自调用list_max,并将Temp的新值作为第一个参数传入。这是函数式语言中常见的做法。在这种情况下,Temp被称为累加器(我通常将变量命名为Acc以反映这种用法,但当然你可以随意命名)。
让我展示另一个解决方案,它可能被视为马塞洛的答案和stmi的答案之间的“折衷方案”。
list_max( [H|T] ) -> list_max( H , T ).

list_max( X , []    ) -> X;
list_max( X , [H|T] ) -> list_max( erlang:max(H, X) , T ).

我还放弃了检测空列表的子句,因为我认为它并没有什么用处——尽管现在如果你使用空列表调用它,它会抛出异常。


1

你也可以使用内置函数来表达:

-module(list_max).
-compile(export_all).

list_max([]) -> none;
list_max([H | T] = List) ->
    lists:foldl(fun erlang:max/2, H, T);
list_max(_) -> badarg.

由于 max 是可结合的,因此您应该使用尾递归的 foldl - Marcelo Cantos
这对我来说太多了,但还是谢谢你。我刚开始在大学学习 Erlang。 - some_id
在这里,当 is_list(List) 几乎没有用处,因为它只检查是否存在 [] 或者 [|]。它并不检查“proper list”。 - Hynek -Pichi- Vychodil
1
@Hynek 嗯...它不是几乎无用...它是完全无用的,因为在列表上进行匹配(使用尖括号)已经告诉您它是一个列表。 - Mazen Harake
实际上,“when”子句完全没有用,所以根据大家的要求,我也进行了更正。 - stmi

1

Erlang 是一种单赋值语言,因此您无法更改“变量”。您只能创建新的变量。

我的建议是查看列表模块。在 lists.erl 中,您会发现:

max([H|T]) -> max(T, H).

max([H|T], Max) when H > Max -> max(T, H);
max([_|T], Max)              -> max(T, Max);
max([],    Max)              -> Max.

你不更新Max变量(在你的例子中是Temp),而是使用新值调用函数或从函数中返回它。

非常简单...:-)


这是正确的例子。它实际上是Erlang列表函数lists:max(L)的本地实现。为什么它更好?请注意,迭代顺序提供了比此处发布的所有其他解决方案都要好的性能。 - Grigore Madalin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接