我在prolog中有这个列表:
List = [functor(a,1),functor(n,7),functor(l,9),functor(k,0)]
我希望按仿函数中的数字而不是字母对其进行排序。
我是说如果我这样做
sort(L,L1)
我会得到
L1 = [functor(a,1),functor(k,0),functor(l,9),functor(n,7)]
但我希望它像
L1 = [functor(k,0),functor(a,1),functor(n,7),functor(l,9)]
有没有办法做到这一点(而不仅仅是重新创建它并将数字放在第一位)
答案 0 :(得分:4)
To"重新创建"清单(种类):
?- List = [functor(a,1),functor(n,7),functor(l,9),functor(k,0)],
map_list_to_pairs(arg(2), List, Pairs),
keysort(Pairs, Sorted_pairs),
pairs_values(Sorted_pairs, Sorted).
Pairs = [1-functor(a, 1), 7-functor(n, 7), 9-functor(l, 9), 0-functor(k, 0)],
Sorted = [functor(k, 0), functor(a, 1), functor(n, 7), functor(l, 9)].
见here。这可能是最常见的"惯用的"这样做的方法,因为你的实现有一个library(pairs)
。如果它没有,那么这里使用的谓词几乎无关紧要:请参阅library source。
如果您使用predsort
,请参阅评论中也链接的the question。您可以定义辅助谓词,如:
compare_2(Order, A, B) :-
arg(2, A, A2),
arg(2, B, B2),
compare(Order, A2-A, B2-B).
(由@false修正)
这将首先对第二个参数进行排序,如果它们相等,则在整个术语上进行排序。
?- List = [f(a,1),f(n,0),f(l,9),f(k,0)],
predsort(compare_2, List, Sorted).
List = [f(a, 1), f(n, 0), f(l, 9), f(k, 0)],
Sorted = [f(k, 0), f(n, 0), f(a, 1), f(l, 9)].
换句话说,它不是一个稳定的排序"。实际上,最好使用keysort
方法。
请注意,此版本的compare_2
仍会删除除第一次出现的相同字词之外的所有字词,因为这是predsort
所做的:
?- List = [f(a,1),f(n,0),f(l,9),f(n,0)],
predsort(compare_2, List, Sorted).
List = [f(a, 1), f(n, 0), f(l, 9), f(n, 0)],
Sorted = [f(n, 0), f(a, 1), f(l, 9)].
你可以"作弊"通过定义两个等效(但不相等)的元素已经排序:
compare_2_stable(Order, A, B) :-
arg(2, A, A2),
arg(2, B, B2),
compare(Order0, A2, B2),
( Order0 == (=)
-> Order = (<)
; Order = Order0
).
?- List = [f(a,1),f(n,0),f(l,9),f(k,0)],
predsort(compare_2_stable, List, Sorted).
List = [f(a, 1), f(n, 0), f(l, 9), f(k, 0)],
Sorted = [f(n, 0), f(k, 0), f(a, 1), f(l, 9)].
?- List = [f(a,1),f(n,0),f(l,9),f(n,0)],
predsort(compare_2_stable, List, Sorted).
List = [f(a, 1), f(n, 0), f(l, 9), f(n, 0)],
Sorted = [f(n, 0), f(n, 0), f(a, 1), f(l, 9)].
请注意,我不确定这是否真的会保留等效元素的原始顺序(元素与&#34;相等&#34;第二项)。就这个例子而言,它现在就是这样做的。只有当predsort
将元素传递给比较谓词时,它们才会保持原始顺序,这可能就是这种情况,这可能取决于实现(??)。
编辑:在SWI-Prolog中查看了predsort/3
的源代码,是的,在SWI-Prolog中,使用当前的实现,最后的解决方案将提供完全相同的解决方案使用keysort/2
。 但是,除非您有实际的理由,否则您应该更喜欢keysort/2
,并且您愿意牺牲可移植性。