计算嵌套列表中不是原子的项数

Count the number of terms that are not atoms in a nested list

我有这些事实:

vehicle(car,blue,[wheel,horn,optional(radio)]).
vehicle(motorcycle,blue,[wheel,optional(navigation),horn]).
vehicle(truck,white,[wheel,horn,optional(trailer)]).

我想计算所有蓝色车辆的所有可选项目(所有“可选”) - 在本例中为 2。 现在我有一个谓词创建一个嵌套列表,其中包含所有蓝色车辆的组件列表:

countAllOptionalComponents:-
    findall(X,vehicle(_,blue,X),S),
    write(S).

[[轮子,喇叭,可选(收音机)],[轮子,可选(导航),喇叭]]

我的想法是将这个嵌套列表传递给另一个谓词以计算所有“子列表”的所有可选组件,但我遇到了麻烦。像这样:

countAllOptionalComponents:-
    findall(X,vehicle(_,blue,X),S),
    countOptComponents(S,N).

countOptComponents([],0).
countOptComponents([X,Y],N):-
[...]

也许我遵循的方法没有多大意义。

一种可能的解决方案如下:

count(C) :-
    findall(X, vehicle(_, blue, X), Ls),
    countOpt(Ls, 0, C).

countOpt([], X, X) :- !.
countOpt([H|T], C, NewC) :-
    countOpt(T, C, NewC1),
    findall(Opt, member(optional(Opt), H), Opts),
    printOpts(Opts),
    length(Opts, Length),
    NewC is NewC1 + Length, !.

printOpts([]).
printOpts([H|T]) :-
    print(H),
    nl,
    printOpts(T).

按照您的方法,首先收集每辆车的所有特征列表(我猜?)并将其保存在名为 Ls 的列表列表中。

然后 select 在 Ls 的每个子列表中的所有可选值 (Opt) 并添加它们的所有长度。

我还添加了谓词来打印结果。

如果您已经在使用 findall() 并且您知道通过将 findall 包装在 () 中间可以有多个目标,那么您可以在其中放置另一个 findall:

countAllOptionalComponents(OptionCount) :-
    findall(CarOptions,
        (vehicle(_, blue, CarAllItems),
         findall(O, member(optional(O), CarAllItems), CarOptions)
        ), AllOptionsNested),
    append(AllOptionsNested, AllOptions),
    write(AllOptions),
    length(AllOptions, OptionCount).

append/2 扁平化嵌套列表,append([[horn], [radio,aircon]], [horn,radio,aircon]).