从我的prolog代码中删除列表中的列表

时间:2013-09-07 20:40:55

标签: list tree prolog

我一直试图解决我的这个问题一段时间了,但我不确定该怎么做。

例如,假设我的数据库中有这个“树”:

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]].

此代码的问题是它生成了多个列在我原始列表中的列表。还有另一种方法可以解决这个问题吗?任何帮助将不胜感激!

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].

正如您从文档中看到的那样,不鼓励使用它,并且您已经收到了许多可以避免它的好提示。