为了更容易理解的版本,我提出以下建议:
:- use_module(library(lists)).
keys_dict_uniquevalues(Ks,D,UVs) :-
keys_dict_values(Ks,D,Vs), % Vs ... values with duplicates
list_set(Vs,UVs). % UVs ... Vs deduplicated
keys_dict_values([],_D,[]). % No keys no values
keys_dict_values([Key|Keys],D,Vs) :-
key_dict_values(Key,D,Matches), % all Matches for Key
keys_dict_values(Keys,D,OtherVs), % Matches for other Keys
append(Matches,OtherVs,Vs). % all found values in Vs
key_dict_values(_K,[],[]). % no mathes if dictionary empty
key_dict_values(K,[(K,V)|Pairs],[V|Vs]) :- % Value is in list if key matches
key_dict_values(K,Pairs,Vs).
key_dict_values(K,[(X,_V)|Pairs],Vs) :- % Value is not in list
dif(K,X), % if key doesn't match
key_dict_values(K,Pairs,Vs).
list_set([],[]). % empty list contains no duplicates
list_set([X|Xs],[X|Ys]) :- % head of the first list
subtract(Xs,[X],Zs), % doesn't occur in Zs
list_set(Zs,Ys).
如果你想编写一个不使用库(列表)的程序,你必须替换 keys_dict_values/3 中的目标 append/3 和 list_set/2 中的目标减去/3。在下面的示例中,lists_appended/3 和 list_x_removed/3:
keys_dict_uniquevalues(Ks,D,UVs) :-
keys_dict_values(Ks,D,Vs),
list_set(Vs,UVs).
keys_dict_values([],_D,[]).
keys_dict_values([Key|Keys],D,Vs) :-
key_dict_values(Key,D,Matches),
keys_dict_values(Keys,D,OtherVs),
lists_appended(Matches,OtherVs,Vs).
key_dict_values(_K,[],[]).
key_dict_values(K,[(K,V)|Pairs],[V|Vs]) :-
key_dict_values(K,Pairs,Vs).
key_dict_values(K,[(X,_V)|Pairs],Vs) :-
dif(K,X),
key_dict_values(K,Pairs,Vs).
lists_appended([],L,L).
lists_appended([X|Xs],Ys,[X|Zs]) :-
lists_appended(Xs,Ys,Zs).
list_set([],[]).
list_set([X|Xs],[X|Ys]) :-
list_x_removed(Xs,X,Zs),
list_set(Zs,Ys).
list_x_removed([],_X,[]).
list_x_removed([X|Xs],X,Ys) :-
list_x_removed(Xs,X,Ys).
list_x_removed([X|Xs],Z,[X|Ys]) :-
dif(X,Z),
list_x_removed(Xs,Z,Ys).
上述示例中给出的查询适用于两个版本:
?- keys_dict_uniquevalues([a,c],[(a,aa),(bb,bbb),(a,aa),(c,def)],X).
X = [aa,def] ? ;
no
?- keys_dict_uniquevalues([a,b],[(a,c),(a,d),(b,c),(b,e),(c,f)],L).
L = [c,d,e] ? ;
no
@false 提供的反例对两个版本都按预期失败:
?- keys_dict_uniquevalues([a,b],[(a,c),(a,d),(b,c),(b,e),(c,f)],[c,c]).
no
@false 建议的不寻常用法:
?- keys_dict_uniquevalues([a,b],[KV1,KV2],[e]).
KV1 = KV2 = (a,e) ? ;
KV1 = (a,e),
KV2 = (b,e) ? ;
KV1 = (a,e),
KV2 = (_A,_B),
dif(b,_A),
dif(a,_A) ? ;
KV1 = (b,e),
KV2 = (a,e) ? ;
KV1 = (_A,_B),
KV2 = (a,e),
dif(b,_A),
dif(a,_A) ? ;
KV1 = KV2 = (b,e) ? ;
KV1 = (b,e),
KV2 = (_A,_B),
dif(b,_A),
dif(a,_A) ? ;
KV1 = (_A,_B),
KV2 = (b,e),
dif(b,_A),
dif(a,_A) ? ;
no