我有一个列表,让我们说X=[a,b,c,d,c,e,d]
,如何删除每个字符中的一个,这样唯一的答案仍然是X1=[c,d]
。
我有一堆只有字母字母的列表,我需要一个命令,如果列表中包含这样的字符,将删除每一个字母,如果没有该字母则不执行任何操作。
我已尝试使用selectchk/3
,但它仅适用于特定情况。
例如,如果我有列表X=[a,b,c,d,d,e,e,f,f,g,h]
,
我可以写selectchk(d,X,X1), selectchk(e,X1,X2), selectchk(f,X2,X3)
等等。
正如我所说,这仅适用于特定情况,但如果我添加一般谓词,请说我每个字母都有selectchk/3
,但是,例如,
新列表为X1=[a,b,c,d,d]
,我使用selectchk(f,X,X3)
,
命令失败,并且没有命名下一个列表X3
,所以下一个命令检查字母' G'列表X3
中的列表无法运行,因为没有此类列表。如果一个失败,是否有可能做OR命令?
X=[a,a,c,d,d,e]
selectchk(a,X,X1)
或(如果没有)append([],X,X1),selectchk(b,X1,X2)
或(如果没有' b'),append([],X2,X3)
等。
由于
答案 0 :(得分:1)
有几种方法可以做到这一点。我认为selectchk/3
构成了一个解决方案的良好基础,这实际上是对#34;自动化"你试图手动做什么并使用递归:
select_each_one(L, R) :-
sort(L, PickList),
select_each_one(L, PickList, R).
select_each_one(L, [H|T], R) :-
selectchk(H, L, R1),
select_each_one(R1, T, R).
select_each_one(L, [], L).
sort
提供了一个"选项列表"仅包含原始列表中每个元素中的一个。然后select_each_one/3
谓词在原始列表的每次迭代中对每个元素执行selectchk
。
?- select_each_one([a,b,c,d,c,e,d], L).
L = [c, d] ;
false.
?- select_each_one([a,b,c,d,d,e,e,f,f,g,h], L).
L = [d, e, f] ;
false.
另一种方法是一次将列表复制到一个元素上,但跟踪我们是否看过该元素:
select_each_one(L, R) :-
select_each_one(L, [], R).
select_each_one([H|T], Seen, R) :-
( member(H, Seen)
-> R = [H|R1], select_each_one(T, Seen, R1)
; select_each_one(T, [H|Seen], R)
).
select_each_one([], _, []).