如何在Erlang中从列表中删除倒数第二个元素

x7rlezfr  于 2023-02-20  发布在  Erlang
关注(0)|答案(1)|浏览(302)

我有个任务:“将list的第二个和第五个元素添加到list的末尾,并删除倒数第二个元素”。我需要在不使用模块lists的情况下完成此操作,只使用递归。
我的代码通过索引查找元素,这解决了查找第二个和第五个元素的问题(对我来说也不是一个理想的解决方案,因为它是相同的lists:nth函数)。

-module(task).

-export([remove_and_add/1]).

remove_and_add(List) ->
    remove_penultimate(List) ++ [nth(2, List)] ++ [nth(5, List)].

nth(1, [H|_]) ->
    H;
nth(N, [_|T]) ->
    nth(N - 1, T).

但是我不明白如何删除没有长度的倒数第二个元素(如何实现remove_penultimate函数)。

euoag5mw

euoag5mw1#

无论何时使用++,您几乎都可以认为自己的效率很低:

remove_penultimate(List) ++ [nth(2, List)] ++ [nth(5, List)].

如果你不能使用列表模块,那么每个初学者需要写的第一个函数就是reverse(List)函数,它不仅是最有用的函数之一,还能教会你如何在函数的参数变量中添加一个“accumulator”变量,以存储你想要的任何数据,下面是一个例子:

go(List) ->
        go(List, []).

    
    go([H|T], Acc) ->  %%  Acc starts off as a blank list, which can be used to store data
       %% maybe do something here
       go(T, [H|Acc]);  %% storing data in the Acc list
    go([], Acc) -> Acc.

使用上面的技巧,您可以向函数的参数添加所需数量的变量,例如:

go(List) ->
    go(List, 1, none, none, []).

go([H|T], N, X, Y, Acc) -> ...

检查此函数:

show_previous(List) ->
        show_previous(List, none).

    show_previous([], Prev) ->  %% A variable called Prev has been added to the function's parameters, and it starts off with the value none.
        io:format("current: end of list, previous: ~w~n", [Prev]);
    show_previous([Last], Prev) ->  %% This clause only matches a list with one element.
        io:format("current: ~w, penultimate: ~w~n", [Last, Prev]),
    show_previous([H|T], Prev) ->
        io:format("current: ~w, prev: ~w~n", [H, Prev]),
        show_previous(T, H).

注意,在Erlang中,一个名称相同但参数变量数量不同的函数(称为函数的“arity”)是一个完全不同的函数,因此show_previous/1show_previous/2是完全不同的函数。
下面是您可以执行的另一个示例:

show([]) ->
    io:format("!No more elements!~n");
show([X, Y]) ->  %% only matches a list with two elements
    io:format("penultimate: ~w, last: ~w~n", [X, Y]),
    show([Y]);
show([H|T]) ->
    io:format("current: ~w~n", [H]),
    show(T).  %% By whittling the list down one element at a time,
              %% the list will eventually become a 2 element list

但是我不知道如何删除没有长度的倒数第二个元素。
你总是可以通过递归所有的元素并计算它们来得到长度。编写你自己的长度函数是一个很好的实践。它非常简单。但是记住,尽可能少地递归列表会更有效,你应该能够通过递归列表一次,然后反转列表(这需要再次递归列表)来解决你最初的问题。
删除倒数第二个元素的另一种可能方法是颠倒列表,然后问自己:“我如何删除列表的第二个元素?”
我提出了一个解决方案,它遍历原始列表一次,当到达列表末尾时,它反转Acc列表并返回它。

[1, 2, 3, 4, 5, 6, 7]

并返回以下列表:

[1,3,4,7,2,5]

我将把这个操作描述为删除列表中的倒数第二个元素并将第二个和第五个元素移到列表末尾,复制第二个和第五个元素并将副本添加到列表末尾也可以用类似的方式解决。

相关问题