[_,[X,_],_]将匹配一个类似[d,[X],a],s]的列表。有没有一种方法可以将其与存在一个或多个匿名变量的任何模式相匹配?即[[X,a],s]和[[d,a]、[p,z]、[X,b]]是否匹配?
我正试图写一个程序来计算列表中的元素,即[a,a,a,b,a,b]=>[[a,4],[b,2]],但我被卡住了:
listcount(L, N) :- listcountA(LS, [], N).
listcountA([X|Tail], [? [X, B], ?], N) :- B is B+1, listcountA(Tail, [? [X,B] ?], N).
listcountA([X|Tail], AL, N) :- listcountA(Tail, [[X,0]|AL], N).
谢谢。
变量与项匹配,anonimus变量也不例外。列表只是头和尾之间的二元关系的语法糖。因此,变量可以匹配列表、头或尾,但不能匹配未指定的序列。
我希望一些笔记能帮助你:
listcount(L,N):-listcountA(LS,[],N)。
在Prolog中,谓词由名称和num.of.arguments标识,即所谓的函子和arity。因此,添加了参数的"服务"谓词通常保持相同的名称。
listcountA([X|Tail],[?[X],B],?],N):-B是B+1,listcountA。
B是B+1永远不会成功,您必须使用一个新变量。而且没有办法在列表中使用通配符进行匹配,而是编写一个谓词来查找和更新计数器。
最后一点:元素的对通常使用二进制关系表示,方便地使用一些(任意)运算符。例如,最常用的是破折号。
所以我会写
listcount(L, Counters) :-
listcount(L, [], Counters).
listcount([X | Tail], Counted, Counters) :-
update(X, Counted, Updated),
!, listcount(Tail, Updated, Counters).
listcount([], Counters, Counters).
update(X, [X - C | R], [X - S | R]) :-
S is C + 1.
update(X, [H | T], [H | R]) :-
update(X, T, R).
update(X, [], [X - 1]). % X just inserted
update/3可以使用一些库谓词来简化,即递归的"内部移动"。例如,使用select/3:
listcount([X | Tail], Counted, Counters) :-
( select(X - C, Counted, Without)
-> S is C + 1
; S = 1, Without = Counted
),
listcount(Tail, [X - S | Without], Counters).
listcount([], Counters, Counters).
我会在这篇文章的开头说,如果你喜欢这个答案,可以考虑将正确答案授予@chac,因为这个答案是基于他们的。
这里有一个版本,它还使用了累加器并处理输入列表中的变量,为您提供了您直接要求的输出项结构:
listcount(L, C) :-
listcount(L, [], C).
listcount([], PL, PL).
listcount([X|Xs], Acc, L) :-
select([X0,C], Acc, RAcc),
X == X0, !,
NewC is C + 1,
listcount(Xs, [[X0, NewC]|RAcc], L).
listcount([X|Xs], Acc, L) :-
listcount(Xs, [[X, 1]|Acc], L).
请注意,listcount/2
遵循基于累加器的版本listcount/3
,后者维护累加器中的计数,并且不假设输入顺序或基本输入列表(命名/标记的变量将正常工作)。
[_,[X,_],_]将只匹配具有3个元素的列表,第一个和第三个元素可以是原子或列表,第二个元素必须是长度为2的列表,但我希望您知道这一点。它与2个元素列表不匹配,最好使用首尾递归来查找元素并将其插入结果列表。这是一个谓词草图,如果复制粘贴,我敢打赌它不会起作用;)
% find_and_inc(+element_to_search, +list_to_search, ?result_list)
find_and_inc(E, [], [[E, 1]]);
find_and_inc(E, [[E,C]|T1], [[E,C1]|T2]) :- C1 is C+1;
find_and_inc(E, [[K,C]|T1], [[K,C]|T2]) :- find_and_inc(E, T1, T2).