我一直试图解决我的这个问题一段时间了,但我不确定该怎么做。
例如,假设我的数据库中有这个“树”:
tree4(b(b(l(Apple),l(Banana)), b(l(Orange), l(Pear)))).
我希望能够查询数据库,以便检索每个l()中的信息并将其显示在列表中。到目前为止,我已经做到了这一点:
leaves(l(X), L) :-
L = X.
leaves(b(X,Y), L) :-
leaves(X, A),
leaves(Y, B),
L = [A, B].
然后我查询数据库,它给了我这个:
?- tree4(T), leaves(T, L).
T = b(b(l(1), l(2)), b(l(3), l(4))),
L = [[1, 2], [3, 4]].
此代码的问题是它生成了多个列在我原始列表中的列表。还有另一种方法可以解决这个问题吗?任何帮助将不胜感激!
答案 0 :(得分:2)
在描述列表时(在本例中为:叶子),请考虑使用DCG:
leaves(l(L)) --> [L].
leaves(b(B1,B2)) --> leaves(B1), leaves(B2).
示例查询(使用原子而不是tree4/1
中的变量):
?- tree4(Tree), phrase(leaves(Tree), Leaves).
Tree = b(b(l(apple), l(banana)), b(l(orange), l(pear))),
Leaves = [apple, banana, orange, pear].
答案 1 :(得分:1)
通过在遍历树期间使用累加器来收集叶子,可以避免append/3
谓词的开销:
leaves(Tree, Leaves) :-
leaves(Tree, [], Leaves).
leaves(l(Leaf), Leaves, [Leaf| Leaves]).
leaves(b(Left,Right), Leaves0, Leaves) :-
leaves(Right, Leaves0, Leaves1),
leaves(Left, Leaves1, Leaves).
使用您的示例电话:
?- leaves(b(b(l(1), l(2)), b(l(3), l(4))), Leaves).
Leaves = [1, 2, 3, 4].
答案 2 :(得分:0)
假设您的Prolog实现具有append
谓词,您可以这样做:
leaves(l(X), [X]).
leaves(b(X,Y), L) :-
leaves(X, A),
leaves(Y, B),
append(A, B, L).
所以leaves
将始终返回一个平面列表,即使只有一个。这也假设您的树是严格二进制的,正如您所描述的那样。
答案 3 :(得分:0)
提醒一下flatten / 2,一个方便的内置:
?- leaves(b(b(l(1), l(2)), b(l(3), l(4))), L), flatten(L, F).
L = [[1, 2], [3, 4]],
F = [1, 2, 3, 4].
正如您从文档中看到的那样,不鼓励使用它,并且您已经收到了许多可以避免它的好提示。