Prolog - 算术平均和合并

Prolog - Arithmetic mean and merge

我在 Prolog 中有这个查询:

?- order([[person1, [7,8,8,9]], [person2, [8,9,8,9]], [person3, [6,7,5,4]]],X).

我需要每个人的算术平均值,然后使用合并排序,就像这样:

X=[[person2,[8,9,8,9],8.5],[person1,[7,8,8,9],8],[person3,[6,7,5,4],5.5]].

我知道如何计算一个列表的算术平均值,但我想在这种情况下我需要一些递归的东西。

有人可以帮助我吗?

将谓词应用于列表的每个成员以获得新列表是 maplist 的目的。对于排序,您可以使用内置的 keysort/2,或者,如果您有最新的 SWI-Prolog 版本,则可以使用 sort/4。但是,如果您使用成对(例如)而不只是列表中的另一个项目(毕竟您知道 "things" 的数量)会更好:

person_vals_mean([P, Vs], Mean-[P, Vs]) :-
    numlist_mean(Vs, Mean). % assuming you have defined it elsewhere

order(PVs, Ordered) :-
    maplist(person_vals_mean, PVs, PVMs),
    keysort(PVMs, Ordered_rev),
    reverse(Ordered_rev, Ordered).

完全删除列表可能是明智的:为什么 [person, [1,2,3]] 而不是 person_vals(person, [1,2,3])?使用这种表示,您可以将 person_vals_mean/2 重写为:

person_vals_mean(person_vals(P, Vs), Mean-person_vals(P, Vs)) :- ...

或者,如果可以使用 sort/4,甚至:

person_vals_mean(person_vals(P, Vs), person_vals_mean(P, Vs, M)) :-
    numlist_mean(Vs, M).

order_by_means(PVs, Ordered) :-
    maplist(person_vals_mean, PVs, PVMs),
    sort(3, @>=, PVMs, Ordered).

然后:

?- order_by_means([person_vals(person1, [7,8,8,9]),
                   person_vals(person2, [8,9,8,9]),
                   person_vals(person3, [6,7,5,4])],
                  Ordered).
Ordered = [person_vals_mean(person2, [8, 9, 8, 9], 8.5),
           person_vals_mean(person1, [7, 8, 8, 9], 8),
           person_vals_mean(person3, [6, 7, 5, 4], 5.5)].

事实上,SWI-Prolog 中的所有排序内置函数都使用归并排序算法,但这是用 C 实现的,实际上无关紧要。