List 如何在prolog中对年龄列表进行排序?

List 如何在prolog中对年龄列表进行排序?,list,sorting,prolog,List,Sorting,Prolog,我试图在序言中按年龄从高到低排列亲属名单: born(kate,date(11,2,1960)). born(marc,date(11,2,1961)). born(I,date(9,3,1962)). born(michel,date(24,4,1963)). born(harry,date(26,5,1964)). born(jess,date(16,1,1965)). born(ruth,date(26,9,1966)). born(fran,date(4,3,1967)). 结果应该是

我试图在序言中按年龄从高到低排列亲属名单:

born(kate,date(11,2,1960)).
born(marc,date(11,2,1961)).
born(I,date(9,3,1962)).
born(michel,date(24,4,1963)).
born(harry,date(26,5,1964)).
born(jess,date(16,1,1965)).
born(ruth,date(26,9,1966)).
born(fran,date(4,3,1967)).
结果应该是一个列表:
[凯特、马克、我、米歇尔、哈里、杰西、露丝、弗兰]

我通过@capelical尝试此代码片段:

pairs_values([], []).
pairs_values([_-V|T0], [V|T]) :-
    pairs_values(T0, T).

by_date(Sorted) :-
  findall(Date-Person, born(Person,Date), List),
  keysort(List, Pairs),
  pairs_values(Pairs, Sorted).
但是这个代码并没有对它进行排序。
我需要在ciao Prolog中完成。我们可以在SWi Prolog中完成,使用一些内置的:

by_date(Sorted) :-
  findall(Date-Person, born(Person,Date), List),
  keysort(List, Pairs),
  pairs_values(Pairs, Sorted).
编辑:pairs\u值非常简单:这里是SWI Prolog片段

%%  pairs_values(+Pairs, -Values) is det.
%
%   Remove the keys  from  a  list   of  Key-Value  pairs.  Same  as
%   pairs_keys_values(Pairs, _, Values)

pairs_values([], []).
pairs_values([_-V|T0], [V|T]) :-
    pairs_values(T0, T).

TL;DR:您得到的序列已排序,但排序标准出乎您的意料

让我们试着重现OP观察到的奇怪行为

$ ciao
Ciao 1.14.2-13646: Mon Aug 15 10:15:33 CEST 2011
?- compile(dmy_vs_ymd).
{Reading /home/stefan/Prolog/dmy_vs_ymd.pl
WARNING: (lns 3-3) [I] - singleton variables in born/2
}
yes
?- by_date(S).
S = [fran,_,kate,marc,jess,michel,harry,ruth] ? ;
no
似乎每个元素都放错了位置(相当大的差异:)

  • 预计:
    [凯特、马克、我、米歇尔、哈里、杰西、露丝、弗兰]
  • 观察:
    [fran,_uu,kate,marc,jess,michel,harry,ruth]
让我们把事实重新排序如下
[弗兰、凯特、马克、杰西、米歇尔、哈里、露丝]
然后检查:

born(fran , date( 4, 03, 1967)). born(I , date( 9, 03, 1962)). born(kate , date(11, 02, 1960)).%\_______________________________________________ born(marc , date(11, 02, 1961)).%/ equal primary & secondary, different tertiary born(jess , date(16, 01, 1965)). born(michel, date(24, 04, 1963)). born(harry , date(26, 05, 1964)).%\____________________________________ born(ruth , date(26, 09, 1966)).%/ equal primary, different secondary % ^^ ^^ ^^^^ % || || |||| % || || \+++------- tertiary sorting criterion % || || % || \+------------ secondary sorting criterion % || % \+------------------ primary sorting criterion 示例查询:

?- by_date(S).
S = [kate,marc,_,michel,harry,jess,ruth,fran].
嗯。。。我们做完了吗

  • 预计:
    [凯特、马克、我、米歇尔、哈里、杰西、露丝、弗兰]
  • 观察:
    [kate,marc,\uz,michel,harry,jess,ruth,fran]
不是100%
I
是一个变量,我们实际上想要一个常数;将其替换为atom
i

这个匿名变量是我们在Ciao Prolog会话开始时收到“singleton variable”警告的原因。嗯

我在“ciao prolog”中尝试了这一点,但它抛出了一个错误“存在错误:过程:用户:pairs\u values/2不存在”我需要在“ciao prolog”中完成,对不起。更简单的是:
findall(Date-p,born(p,Date),L0),keysort(L0,L1),findall(p,member(u-p,L1),L2)。
@larsman:有趣,而且可能更高效。在没有垃圾收集的情况下(我不知道Ciao Prolog是否有垃圾收集),findall使用所需的最小空间。我肯定会使用
sort/2
代替
keysort/2
,因为
sort/2
删除重复项和同龄人员的(准随机)顺序。我真的很想使用
setof/3
,但是当
born/2
没有解决方案时,它失败了(出于一些好的原因),而不是给出一个空列表。而否决投票的原因是@德米特里:在这个问题上,Ciao没有什么特别的,因此标签不合适。将标签保留在有特定问题的问题上。
?- by_date(S).
S = [kate,marc,_,michel,harry,jess,ruth,fran].