场景
我有以下代码。我的问题是如何不多次出现相同的结果。
let foo = {
bar: function() {
console.log('foo.bar()');
}
};
当前输出
我需要的
我需要输出为Charles,Ann,Andrew,Edward。没有名字重复。
答案 0 :(得分:4)
在相当新的版本中,您可以使用库(solution_sequences):
?- distinct(nextking(X)).
X = charles ;
X = ann ;
X = andrew ;
X = edward.
或使用内置的经典“所有解决方案”:
?- setof(K,K^nextking(K),Ks),member(X,Ks).
Ks = [andrew, ann, charles, edward],
X = andrew ;
Ks = [andrew, ann, charles, edward],
X = ann ;
...
但是在这种情况下,我们放宽了知识库中定义的答案顺序。
答案 1 :(得分:1)
您的nextking/1
谓词效率很低,而且不能保证按年龄对人员进行排序。
例如,如果我们将charles
放在事实列表的最后,我们将得到:
?- nextking(X).
X = ann ;
X = ann ;
X = andrew ;
X = charles ;
X = charles ;
X = charles ;
X = edward.
基本上您写的谓词有两个子句:
nextking(X) :-
age(X,P),
age(Y,Q),
P >= Q,
X\==Y.
nextking(X) :-
age(X, 55).
第一个简单地将产生任何X
年龄较小的人Y
。但这并不能保证对这些元素进行排序。最后,最后一个谓词将与所有55岁的人X
统一。对于这种特定情况,这是可行的,但这意味着如果我们声明另一个事实age(louise, 14)
,则此操作将失败。这种方法不仅不正确,而且即使正确,也会非常“不稳定”。
我们可以利用setof/3
[swi-doc]谓词,该谓词不仅执行唯一性过滤器,而且还对元素进行排序。
由于我们要按降序对王室成员进行排序,因此,我们应该构造2元组(或封装两个参数的其他结构),其中第一个参数包含负年龄,第二个参数表示对应的人。
然后我们可以使用member/2
[swi-doc]来“展开”单个统一的列表:
nextking(X) :-
setof((NA, X), A^(age(X, A), NA is -A), Royals),
member((_, X), Royals).
这将产生如下元素列表:
?- nextking(X).
X = charles ;
X = ann ;
X = andrew ;
X = edward.
无论事实如何在源文件中排序。