排序基于第三个元素的列表列表并返回第一个元素

时间:2013-12-31 14:09:14

标签: prolog

如何对包含[[A,B,2000],[C,D,2008],[F,G,2004]]的列表列表进行排序 基于每个列表中的最后一个元素,并返回前两个元素,如上例所示。那是[[A,B],[F,G],[C,D]]

1 个答案:

答案 0 :(得分:2)

请注意,以大写字母开头的单词是变量,而不是原子。从问题陈述中不清楚它是否意图列表元素是变量。我会假设它们是变量,因为它不会影响建议的解决方案。

可能有很多方法可以做到这一点,但这里有一种方法,我不认为是最佳方式:

1)使用setof以不同的顺序收集排序的值。也就是说,将您的列表收集为一个如下所示的新列表:[[2000,A,B],[2004,F,G],[2008,C,D]]。这假定每个列表项都是唯一的(没有所需的重复项)。

2)编写一个通过新列表的简单谓词,并删除每个子列表的第一个元素。

最终解决方案如下:

process( L, Result ) :-
    setof([Z,X,Y], member([X,Y,Z], L), SortL),  % gives list like shown above
    stripyear(SortL, Result).

stripyear是一个谓词,它将遍历每个列表项并去除年份(每个子列表的第一个元素)。它非常简单,遵循基本的Prolog列表处理原则:

stripyear([[_,B,C]|T1], [[B,C]|T2]) :-...

这里主要条款的头部说如果我的输入是一个看起来像[[_,B,C]|T1]的列表,那么输出就是一个看起来像[[B,C]|T2]的列表。也就是说,第二个列表的头部是第一个列表的头部,其第一个元素被删除。我们不关心该元素的价值,因此我们使用_来显示它。但接下来我们需要处理T1T2。它们有什么关系?我已经照顾好了头脑。尾部以相同的方式递归相关:第二个列表的尾部是第一个列表的尾部,其中删除了年份(第一个子列表元素):stripyear(T1, T2)。所以完整的主要条款如下:

stripyear([[_,B,C]|T1], [[B,C]|T2]) :- stripyear(T1, T2).

这很棒,但它是如何停止的?如果我有一个空列表(striplist([], ?))怎么办?列表[][[_,B,C]|T1]不匹配,因为它没有头部或尾部。它是空的。如果没有处理它的条款,striplist([], Result)就会失败。所以我需要一个子句来单独处理它,它也总结了递归:

stripyear([], []).

这说明如果我从空列表中剥离年份,我会得到一个空列表。很合乎逻辑。