以您的示例和@ false的評論爲例,實際問題似乎是從每個子列表中刪除發生在任何其他子列表中的元素。我的困難將其概念化爲單詞,導致我構建了我認爲是非常混亂和粗糙的一段代碼。
所以首先我想要一個小助手謂詞排序member/2
直到列表子列表。
in_sublist(X, [Sublist|_]) :- member(X, Sublist).
in_sublist(X, [_|Sublists]) :- in_sublist(X, Sublists).
這是沒有很大的一塊工作,並於實話我覺得,因爲我只是不能看到自己曾經想使用這個對自己應該以某種方式內聯。
現在,我最初的解決方案是不正確的,看起來像這樣:
remove([Sub1|Subs], [Res1|Result]) :-
findall(X, (member(X, Sub1), \+ in_sublist(X, Subs)), Res1),
remove(Subs, Result).
remove([], []).
你可以看到那種主題的我要去這裏雖然:讓我們用findall/3
枚舉子列表的元素在這裏然後我們可以過濾掉其他列表中出現的那些。這並不完美,輸出看起來像這樣。
?- remove([[a,m,t,a],[k,a,w],[i,k,b,b],[z,m,m,c]], R).
R = [[t], [a, w], [i, k, b, b], [z, m, m, c]].
所以,它開始尋求與[t]
OK,但隨後失去與[a,w]
的情節,因爲沒有可視性輸入[a,m,t,a]
當我們到達第一個遞歸調用。有幾種方法可以處理它;一個聰明的人可能會形成一種拉鍊,我們將列表中的前面的元素和後面的元素放在一起。另一種方法是在遞歸調用之前從所有後續列表中刪除列表中的元素。我選擇了一個「更簡單」的解決方案,該解決方案更加複雜,難以閱讀,但花費的時間更少。我強烈建議您調查其他可讀性選項。
remove(In, Out) :- remove(In, Out, []).
remove([Sub1|Subs], [Res1|Result], Seen) :-
findall(X, (member(X, Sub1),
\+ member(X, Seen),
\+ in_sublist(X, Subs)), Res1),
append(Sub1, Seen, Seen1),
remove(Subs, Result, Seen1).
remove([], [], _).
所以基本上現在我保持一個「看到」列表。在遞歸調用之前,我把目前爲止所看到的東西以及這個列表中的元素縫合在一起。這不是特別有效,但它似乎完成了這項工作:
?- remove([[a,m,t,a],[k,a,w],[i,k,b,b],[z,m,m,c]], R).
R = [[t], [w], [i, b, b], [z, c]].
這讓我覺得很討厭的問題。老實說,我很驚訝這是多麼令人討厭。我希望別人能夠走到一起,找到更好的解決方案。
要調查的另一件事是DCGs,這可以幫助做這些類型的列表處理任務。
爲什麼'X = [[T],[K,W],[I,B,B],[Z,C]] '?在[[a,m,t,a],[k,a,w],[i,k,b,b],[z,m,m,c]]'和'b在解決方案中出現兩次。這沒有多大意義。 – lurker
抱歉,這是我的錯誤 – user
@lurker:'b,b'在這裏是因爲它只出現在一個子列表中 - 大概是 – false