从元组列表中的元组获取第二个项目

时间:2018-09-17 07:58:05

标签: prolog

因此,自从我开始使用AI和FOL以来,我最近开始使用prolog。我注意到与我使用的其他语言(例如Python和Java)有很多差异,并且在尝试“比较”这些语言时遇到了困难。

我遇到的主要问题是我不知道如何建立规则以获取列表中第二个元组的列表。

输入是一个元组列表,例如:[(1,aa),(2,bb),(3,cc),(4,dd)]

我正在尝试编写一个函数,使输出为列表中每个元组的第二个项目的列表,即[aa,bb,cc,dd]

我已经尝试按照“ extract_second_item([(1,aa),(2,bb),(3,cc),(4,dd)], [(_ , output)|_])”的方式做一些事情。但是,当我运行该函数时,它仅返回第一个元组(aa)的第二个项目,而其余部分显然不返回。

谢谢!

2 个答案:

答案 0 :(得分:4)

您需要使用简单的递归:

extract_second_item([], []).
extract_second_item([(_,X)|T], [X|T2]):- extract_second_item(T,T2).

现在查询:

?- extract_second_item([(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].

@lurker提出的另一种很棒的方法是使用maplist/3

首先,我们定义一个简单的谓词,该谓词从元组返回第二项:

second_item((_,X), X).

然后我们使用maplist/3将second_item / 2映射到列表中的每个元组:

?-maplist(second_item, [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].

答案 1 :(得分:2)

实际上,元组是一个复合物:

?- write_canonical((a,b,c)).
','(a,','(b,c))
true.

因此arg / 3可以很方便地从元组中按位置提取第二个参数:

?- arg(2,(a,b),X).
X = b.

您可以使用lambda表达式以紧凑的方式解决问题

?- maplist([X,Y]>>arg(2,X,Y), [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].

在Prolog中并没有广泛使用音色,确实,该问题有一个更简单的解决方案,直接应用模式匹配:

?- maplist([X,Y]>>(X=(_,Y)), [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].

模式匹配可以在lambda参数中推送:

?- maplist([(_,Y),Y]>>true, [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].

您可以选择库(lambda)而不是库(yall),以交易速度提高便携性:

?- use_module(library(lambda)).
true.

?- maplist(\X^Y^(X=(_,Y)), [(1,aa),(2,bb),(3,cc),(4,dd)], L).
L = [aa, bb, cc, dd].

在SWI-Prolog中,这需要您安装pack(lambda),

?- pack_install(lambda).