我一直在尝试将给定列表拆分为两个不同的列表:唯一和重复.例如,如果我们有列表,[1, 1, 2, 3, 3, 4, 5]
我希望唯一列表是[2, 4, 5]
和重复[1, 3]
.我不希望列表中的所有1都在重复列表中.我只需要其中一个.我现在的代码:
compareL([_|[]], Unique, Dup).
compareL([X3,Y3 | Tail], [X3 | Unique], Dup) :-
X3 =\= Y3,
compareL([Y3 | Tail], Unique, Dup).
compareL([X3,Y3 | Tail], Unique, [X3 | Dup]) :-
X3 = Y3,
skipDups(X3, Tail, Unique, Dup).
skipDups(_, [], Unique, Dup).
skipDups(X3,[Y3 | Tail], Unique, Dup) :-
X3 =\= Y3,
compareL([Y3 | Tail], Unique, Dup).
skipDups(X3,[Y3 | Tail], Unique, Dup) :-
X3 = Y3,
skipDups(X3, Tail, Unique, Dup).
Run Code Online (Sandbox Code Playgroud)
使用上面给出的示例列表,如果我运行,compareL([1, 1, 2, 3, 3, 4, 5], Unique, Dup).
我得到:
Unique = [2, 4|_G1954],
Dup = [1, 3|_G1948].
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚为什么在两个列表的末尾我得到' _G1954
'和' _G1948
'.任何帮助,将不胜感激.谢谢.
我们可以通过建立和,保持逻辑纯度!if_/3
(=)/3
tpartition/4
list_uniqs_dups([],[],[]).
list_uniqs_dups([X|Xs0],Us0,Ds0) :-
tpartition(=(X),Xs0,Es,Xs),
if_(Es=[],
Us0+Ds0=[X|Us]+Ds,
Ds0+Us0=[X|Ds]+Us),
list_uniqs_dups(Xs,Us,Ds).
Run Code Online (Sandbox Code Playgroud)
这是OP给出的查询:
?- list_uniqs_dups([1,1,2,3,3,4,5],Us,Ds).
Ds = [1,3], Us = [2,4,5]. % succeeds deterministically
Run Code Online (Sandbox Code Playgroud)
好!以下相当普遍的查询怎么样?
?- list_uniqs_dups([],Us,Ds). Ds = [], Us = []. ?- list_uniqs_dups([A],Us,Ds). Ds = [], Us = [A]. ?- list_uniqs_dups([A,B],Us,Ds). Ds = [B], Us = [] , A=B ; Ds = [] , Us = [A,B], dif(A,B). ?- list_uniqs_dups([A,B,C],Us,Ds). Ds = [C], Us = [] , A=B , B=C ; Ds = [B], Us = [C] , A=B , dif(B,C) ; Ds = [C], Us = [B] , A=C , dif(B,C) ; Ds = [C], Us = [A] , dif(A,C), B=C ; Ds = [] , Us = [A,B,C], dif(A,B), dif(A,C), dif(B,C).
使用答案 (=)/3
list_uniqs_alldups(Es,Us,Ds) :
tpartition(list_uniqmember_t(Es),Es,Us,Ds).
list_uniqmember_t(Es,X,T) :-
tfilter(=(X),Es,Xs),
=(Xs,[X],T).
Run Code Online (Sandbox Code Playgroud)
示例查询:
?- list_uniqs_alldups([1,1,2,1,1,3,4,3],Us,Ds).
Us = [2, 4],
Ds = [1, 1, 1, 1, 3, 3].
?- list_uniqs_alldups([1,1,2,3,3,1,1,3,4,3],Us,Ds).
Us = [2, 4],
Ds = [1, 1, 3, 3, 1, 1, 3, 3].
?- list_uniqs_alldups([8,1,1,2,3,3,1,1,3,4,3],Us,Ds).
Us = [8, 2, 4],
Ds = [1, 1, 3, 3, 1, 1, 3, 3].
?- list_uniqs_alldups(X,Us,Ds).
X = Us, Us = Ds, Ds = [] ;
X = Us, Us = [_A], Ds = [] ;
X = Ds, Us = [], Ds = [_A,_A] ;
X = Ds, Us = [], Ds = [_A,_A,_A] ;
...
Run Code Online (Sandbox Code Playgroud)
对于我使用的游程编码splitlistIfAdj/3
.
list_rle(List,Rle) :-
splitlistIfAdj(dif,List,Rle0),
maplist(rle_length,Rle0,Rle).
rle_length([H|T],RleLen) :-
length([H|T],L),
RleLen = L*H.
Run Code Online (Sandbox Code Playgroud)
查询:
?- list_rle([a,a,b,a,a,c,d,c],X).
X = [2*a, 1*b, 2*a, 1*c, 1*d, 1*c].
Run Code Online (Sandbox Code Playgroud)
我不知道如何更改它,以便它可以在两个方向上工作.
你也可以这样做:
new_list_uniqs_alldups(List,Us,Ds):-
list_rle(List,Rle),
tpartition(singlelist_t,Rle,Us,Ds).
singlelist_t(L,T) :-
L=N*_,
if_(N=1,T=true,T=false).
Run Code Online (Sandbox Code Playgroud)
样品Q:
?- new_list_uniqs_alldups([1,1,2,1,1,3,4,1,1,7,8],U,D).
U = [1*2, 1*3, 1*4, 1*7, 1*8],
D = [2*1, 2*1, 2*1].
?- new_list_uniqs_alldups([7,7,7,2,1,1,3,4,1,1,7,8],U,D).
U = [1*2, 1*3, 1*4, 1*7, 1*8],
D = [3*7, 2*1, 2*1].
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
625 次 |
最近记录: |