有幾個問題與您的代碼:
您使用謂詞isNum
自己定義的,但只有6
似乎是一個數字。 0
是不是一個數字?所以糾正這種給:
isNum(0).
isNum(6).
或使用swi-prolog的內置謂詞number/1
。 (因爲number/1
沒有實例化給定的變量,所以使用number/1
稍微修改了語義;只要你只在一個方向上使用謂詞 - 列表到子列表 - 並且不使用未被實例化的變量,那很好)。
其次謂詞本身。首先,你以某種方式交換了這些情況:在這裏它會將H
添加到第三個子句中的結果列表中(其中H
不是數字)。此外,在第二個子句中,向列表中添加短劃線(-
)(這似乎不是所需的行爲)。一個更好的謂詞因此可能:
findNumber([],[]).
findNumber([H|T],[H|TAfter]) :-
number(H),
findNumber(T,TAfter).
findNumber([H|T],TAfter):-
not(number(H)),
findNumber(T,TAfter).
或者您也可以通過使用切(!
)使謂詞更緊湊(和更快一點):
findNumber([],[]).
findNumber([H|T],[H|TAfter]) :-
number(H),
!,
findNumber(T,TAfter).
findNumber([_|T],TAfter):-
findNumber(T,TAfter).
演示(swipl
):
?- findNumber([g,o,o,d,j,0,6],X).
X = [0, 6].
?- findNumber([g,o,0,o,d,j,6],X).
X = [0, 6].
遞歸表結構
如果您想遞歸執行此操作,可以通過將謂詞擴展爲三個參數版本findNumber/3
來完成此操作。首先,我們對findNumber/3
地圖有兩個參數findNumber/2
版本:
findNumber(A,B) :-
findNumber(A,B,[]).
(先前定義的謂語應該被刪除)。
接下來,我們定義了以下條款:
findNumber([],TT,TT).
findNumber([H|T],[H|TA],TT) :-
number(H),
!,
findNumber(T,TA,TT).
findNumber([H|T],TA,TT):-
findNumber(H,TA,TL),
!,
findNumber(T,TL,TT).
findNumber([_|T],TA,TT) :-
findNumber(T,TA,TT).
這適用於一種叫做差異列出這將是相當內存和CPU效率。此外,調用堆棧只會增加給定列表的級別數量。
第三個參數指定應將哪個值放在列表的尾部。顯然,基本情況是該列表應該以[]
(這是我們用findNumber/2
至findNumber/3
轉換完成的操作。
存在這樣的Prolog會懷疑是否有子列表(第二條),它會調用findNumber/3
與列表findNumber(H,TA,TL)
的頭,會生成一個列表TA
不留尾巴TL
開放的一個特例。新的尾巴TL
將比後來填寫呼叫findNumber(H,TL,TT)
(因此我們將把我們的原始尾部TT
置於真實背部,但需要中間尾部TL
)。
演示(swipl
):
?- findNumber([[g,0,0,d],[n,4,s,t,y]],K).
K = [0, 0, 4].
?- findNumber([[g,0,0,d],[n,4,[s,3,9],t,y]],K).
K = [0, 0, 4, 3, 9].
幾乎:' - 包括(數字,並[g,鄰,鄰,d,J,0,6],NS).' – CapelliC
@CapelliC如何?我是否要做一個列表清單,如果我有,例如。 [[g,o,o,d],[6,0,0,d]] => [6,0,0]?是否有可能爲多個列表做? – Tyler