1

给定给定车站的一组路线,例如我们:

route(TubeLine, ListOfStations).

route(green, [a,b,c,d,e,f]).
route(blue, [g,b,c,h,i,j]).
...

我需要找到具有共同特定车站的线路名称。结果必须是有序的,具有非重复站,并且如果没有结果,则必须返回一个空列表。所以,查询

| ?- lines(i, Ls).

应该给:

Ls = [blue,red,silver] ? ;
no

我尝试执行以下操作:

lines(X, L) :- setof(L1, findall(W, (route(W, Stations),member(X, Stations)),L1), L).

但是,它给出了以下答案:

Is = [[blue,silver,red]];
no

所以用双括号无序。我尝试仅使用 findall,但结果未排序。我知道我可以编写排序函数并通过它,但是我想知道在这种情况下是否可以只使用 findall 和 setof ?

4

1 回答 1

2

实际上,这比您的尝试更容易,但您需要掌握自由变量的特殊 setof 行为,并考虑需要未知站点的可能性(如果没有解决方案,setof/3 将失败)。

 lines(X, Ls) :-
   setof(L, Stations^(route(L, Stations), member(X, Stations)), Ls)
   -> true ; Ls = [].

正如您所说,一个更简单的替代方法是完全按照您的方式使用 findall/3(没有 setof!),并对输出进行排序。

于 2017-01-06T16:03:24.500 回答