单程:
frequencies_of( [] , [] ) . % empty list? success!
frequencies_of( [X|Xs] , [F|Fs] ) :- % non-empty list?
count( Xs , X:1 , F , X1 ) , % count the occurrences of the head, returning the source list with all X removed
frequencies_of( X1 , Fs ) % continue
. %
count( [] , F , F , [] ) . % empty list? success: we've got a final count.
count( [H|T] , X:N , F , Fs ) :- % otherwise...
H = X , % - if the head is what we're counting,
N1 is N+1 , % - increment the count
count( T , X:N1 , F , Fs ) % - recurse down
. %
count( [H|T] , X:N , F , [H|Fs] ) :- % otherwise...
H \= X , % - if the head is NOT what we're counting
count( T , X:N , F , Fs ) % - recurse down, placing the head in the remainder list
. %
另一种看待它的方式:
frequencies_of( Xs , Fs ) :- % compile a frequency table
frequencies_of( Xs , [] , Fs ) % by invoking a worker predicate with its accumulator seeded with the empty list
.
frequencies_of( [] , Fs , Fs ) . % the worker predicate ends when the source list is exhausted
frequencies_of( [X|Xs] , Ts , Fs ) :- % otherwise...
count( X , Ts , T1 ) , % - count X in the accumulator
frequencies_of( Xs , T1 , Fs ) % - and recursively continue
. %
count( X , [] , [X:1] ) . % if we get to the end, we have a new X: count it
count( X , [X:N|Ts] , [X:N1|Ts] ) :- % otherwise, if we found X,
N1 is N+1 % - increment the count
. % - and end.
count( X , [T:N|Ts] , [T:N|Fs] ) :- % otherwise
X \= T , % - assuming we didn't find X
increment( X , Ts , Fs ) % - just continue looking
. % Easy!
第三种方法是首先对列表进行排序,而不删除重复项。一旦列表被排序,一个简单的 1-pass,有序列表的运行长度编码就会为您提供频率表,如下所示:
frequencies_of( Xs , Fs ) :- % to compute the frequencies of list elements
msort( Xs , Ts ) , % - sort the list (without removing duplicates)
rle( Ts , Fs ) % - then run-length encode the sorted list
. % Easy!
rle( [] , [] ) . % the run length encoding of an empty list is the empty list.
rle( [H|T] , Rs ) :- % the run length encoding is of a non-empty list is found by
rle( T , H:1 , Rs ) % invoking the worker on the tail with the accumulator seeded with the head
. %
rle( [] , X:N , [X:N] ) . % the end of the source list ends the current run (and the encoding).
rle( [H|T] , X:N , Rs ) :- % otherwise...
H = X , % - if we have a continuation of the run,
N1 is N+1 , % - increment the count
rle( T , X:N1 , Rs ) % - and recursively continue
. %
rle( [H|T] , X:N , [X:N|Rs] ) :- % otherwise...
H \= X , % - if the run is at an end,
rle( T , H:1 , Rs) % - recursively continue, starting a new run and placing the current encoding in the result list.
. %