Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Recursion 使用递归从列表中选择唯一项_Recursion_Erlang - Fatal编程技术网

Recursion 使用递归从列表中选择唯一项

Recursion 使用递归从列表中选择唯一项,recursion,erlang,Recursion,Erlang,作为对昨天问题的后续行动 在Erlang中,假设我想从给定列表中选择所有唯一的项,例如 List = [foo, bar, buzz, foo]. 我用了你的结果 NewList = [bar, buzz]. 如何在Erlang中进一步操作NewList 例如,假设我不仅要从列表中选择所有唯一的项,还要计算NewList中所有结果项的字符总数?您可以使用折叠在结果列表上递归。为了简单起见,我将您的原子转换为字符串,您可以使用list_to_atom/1执行此操作: 1> NewList

作为对昨天问题的后续行动

在Erlang中,假设我想从给定列表中选择所有唯一的项,例如

List = [foo, bar, buzz, foo].
我用了你的结果

NewList = [bar, buzz].
如何在Erlang中进一步操作NewList


例如,假设我不仅要从列表中选择所有唯一的项,还要计算NewList中所有结果项的字符总数?

您可以使用折叠在结果列表上递归。为了简单起见,我将您的原子转换为字符串,您可以使用list_to_atom/1执行此操作:

1> NewList = ["bar", "buzz"].
["bar","buzz"]
2> L = lists:foldl(fun (W, Acc) -> [{W, length(W)}|Acc] end, [], NewList).        
[{"buzz",4},{"bar",3}]
这将返回一个可访问的proplist,如下所示:

3> proplists:get_value("buzz", L).
4

如果您想自己构建递归以达到教学目的,而不是使用列表:

count_char_in_list([], Count) ->
    Count;
count_char_in_list([Head | Tail], Count) ->
    count_char_in_list(Tail, Count + length(Head)). % a string is just a list of numbers
然后:

1> test:count_char_in_list(["bar", "buzz"], 0).
7

在函数式编程中,我们有频繁出现的模式,它们应该有自己的名称和支持函数。两个最广泛使用的是地图和折叠有时减少。这两个函数构成了列表操作的基本构造块,通常无需编写专用的递归函数

地图 map函数按顺序迭代列表,生成一个新列表,其中每个元素都是将函数应用于原始列表中相应元素的结果。以下是典型地图的实现方式:

map(Fun, [H|T]) -> % recursive case
    [Fun(H)|map(Fun, T)];
map(_Fun, []) -> % base case
    [].
这是递归函数的完美入门示例;粗略地说,函数子句要么是递归情况,导致使用较小的问题实例调用iself,要么是基本情况,不进行递归调用

那个么你们如何使用地图呢?请注意,第一个参数Fun应该是一个函数。在Erlang中,可以声明有时称为lambdas inline的匿名函数。例如,要将列表中的每个数字平方,请生成一个平方列表:

map(fun(X) -> X*X end, [1,2,3]). % => [1,4,9]
这是一个例子

注意,map是Erlang标准库的一部分,如list:map/2

折叠 map在一个列表和另一个列表之间创建1:1的元素映射,而fold的目的是对列表中的每个元素应用一些函数,同时累积单个结果,例如sum。正确的折叠有助于将其视为向右折叠,可能看起来是这样的:

foldr(Fun, Acc, [H|T]) -> % recursive case
    foldr(Fun, Fun(H, Acc), T);
foldr(_Fun, Acc, []) -> % base case
    Acc.
使用此函数,我们可以对列表中的元素求和:

foldr(fun(X, Sum) -> Sum + X, 0, [1,2,3,4,5]). %% => 15
请注意,foldr和foldl都是列表模块中Erlang标准库的一部分

虽然这可能不是很明显,但一大类常见的列表操作问题可以单独使用map和fold来解决

递归思考 编写递归算法一开始可能会让人望而生畏,但当您习惯了它之后,它就变得非常自然了。遇到问题时,您应该确定两件事:

如何将问题分解为更小的实例?为了使递归有用,递归调用必须以较小的问题作为参数,否则函数永远不会终止。 基本情况是什么,即终止标准?

关于1,考虑计数列表元素的问题。这怎么可能分解成更小的子问题呢?好吧,这样想:给定一个非空列表,其第一个元素头是X,其余元素尾是Y,其长度为1+Y的长度。由于Y小于列表[X | Y],我们成功地减少了问题

继续列表示例,我们什么时候停止?嗯,最终,尾巴将是空的。我们回到基本情况,即空列表的长度为零的定义。您会发现,为各种情况编写函数子句非常类似于为字典编写定义:

%% Definition:
%% The length of a list whose head is H and whose tail is T is
%% 1 + the length of T.
length([H|T]) ->
    1 + length(T);
%% Definition: The length of the empty list ([]) is zero.
length([]) ->
    0.

谢谢你迄今为止的回答。但是,我不想再次手动输入列表,也就是说,我对次要的字符计数功能不太感兴趣,而是更关心如何将使原始列表唯一的结果“延续”到自动使用结果进行进一步操作,无论是计数字符还是其他操作。谢谢,NewList是一个变量,使用它就行了。你能详细说明一下吗?当然可以。假设我的列表是list=[foo,bar,buzz,foo]。我想要所有独特物品的总字符数。进一步假设我使用了uniquesL->uniquesL,[],[]代码。uniques[],ux,Acc->list:reverseAcc;uniques[X | Rest],Seen,Acc->case list:memberX,Seen of true->uniquesRest,Seen,list:deleteX,Acc;false->uniquesRest,[X|Seen],[X|Acc]结束。代码,以便获得唯一的项目。我需要如何修改代码smippet以获得字符数,就像一个例子一样?uniques_and_charsL->uniques=uniquesL,num_charsUniques。请注意,您正在使用fold重新创建映射,因为您正在使用1:1元素映射创建一个列表。非常好的解释。非常感谢你。正是我所需要的。试图将你的指导应用到一个具体的例子中,但仍然有点不确定:假设我的列表是list=[a,b,c,a]。我需要总的n o。仅限所有唯一项的字符。进一步假设我现在使用了uniquesL->uniquesL,[],[]。uniques[],ux,Acc->list:reverseAcc;uniques[X | Rest],Seen,Acc->case list:memberX,Seen of true->uniquesRest,Seen,list:deleteX,Acc;false->uniquesRest,[X|Seen],[X|Acc]结束。以获取唯一的项目。作为一个例子,我将如何更改此代码smippet以同时获取字符数?很多很多,uniques的输出是另一个列表,对吗?将该列表作为输入传递给下面的William Cummings:在列表中组合函数可能非常强大。您可以将其视为从一个Unix命令到另一个Unix命令的管道输出。