2016-11-23 82 views
0

我想要做的是將兩個列表中的元素添加到另一個列表中,最後在控制檯中獲取新列表的值。 我的名單是:A = [a,b]; B(對的列表)= [(c,cc),(a,aa),(b,bb)] 如果第一個元素與第一個元素匹配,我想添加列表B的第二個元素字典原理)我想要將所有這些元素添加到控制檯將輸出的空列表中。 我到目前爲止是這樣的(X將是空列表):如何在prolog中「返回」一個值?

aa(_, [], _) :- 
    true. 

aa([H|T], [(A, B)|T2], X) :- 
    H == A -> 
     append([B], X, X2), aa([H|T], T2, X2); 
     aa([H|T], T2, X). 

在控制檯我打字:read(X), trace,aa([a, b], [(c, cc), (a, aa), (b, bb)], X), write(X).

但它一直返回X的[]值如何,我可以如果我要求X,那麼得到X2的值作爲輸出? 下面是跟蹤輸出:

Call:aa([a, b], [(c,cc), (a,aa), (b,bb)], []) 
Call:a==c 
Fail:a==c 
Redo:aa([a, b], [(c,cc), (a,aa), (b,bb)], []) 
Call:aa([a, b], [(a,aa), (b,bb)], []) 
Call:a==a 
Exit:a==a 
Call:lists:append([aa], [], _2110) 
Exit:lists:append([aa], [], [aa]) 
Call:aa([a, b], [(b,bb)], [aa]) 
Call:a==b 
Fail:a==b 
Redo:aa([a, b], [(b,bb)], [aa]) 
Call:aa([a, b], [], [aa]) 
Exit:aa([a, b], [], [aa]) 
Exit:aa([a, b], [(b,bb)], [aa]) 
Exit:aa([a, b], [(a,aa), (b,bb)], []) 
Exit:aa([a, b], [(c,cc), (a,aa), (b,bb)], []) 
Call:write([]) 
[] 
Exit:write([]) 

回答

1

這不是把;在一行的末尾是一個好主意,這是很容易忽視它。我更喜歡不同的格式,見下文。至於你的問題,你有錯誤的順序append/3的論據。 X2是從遞歸調用中間結果,並且希望「迴歸」的結果是這樣的X2與元素B的組合:

aa(_, [], _) :- 
    true. 

aa([H|T], [(A, B)|T2], X) :- 
    ( H == A 
    -> append([B], X2, X), aa([H|T], T2, X2) 
    ; aa([H|T], T2, X)). 

目標append([B], X2, X)可以更清楚地寫爲X = [B|X2]

這解決眼前的問題,但尚未整個謂語:

?- aa([a, b], [(c, cc), (a, aa), (b, bb)], X). 
X = [aa|_G22] ; 
false. 

您分解的第一個參數爲[H|T],但實際上並沒有一個遞歸超過這個名單,所以你從來不看b和它的對應列表中的對應元素。

這裏有一個簡單的方法做這件事:

aa([], _Pairs, []). 
aa([Key|Keys], Pairs, Values) :- 
    ( member((Key, Value), Pairs) 
    -> aa(Keys, Pairs, Values0), 
     Values = [Value|Values0] 
    ; aa(Keys, Pairs, Values)). 

這裏的關鍵見解是,一旦你知道Key,你可以看看你對列表中的對(Key, Value)Value尚未綁定到值,並且將通過member/2進行實例化,如果該列表包含第一個元素爲Key的對。這是統一的力量!

這似乎工作:

?- aa([a, b], [(c, cc), (a, aa), (b, bb)], X). 
X = [aa, bb]. 

最後,你可能不希望有此之前read(X),因爲這意味着用戶必須預測的解決方案!

+0

這很迷人!唯一的情況是,代碼應該通過case對象具有多個翻譯的整個對列表。這可以通過在'aa(Keys,Pairs,Values0)'行循環通過Pairs之前的謂詞的另一個遞歸調用來實現嗎? – Oskars

+1

有幾種可能的方法來對待它。如果你將' - >'改成'* - >',它會在回溯時列舉出不同的解決方案:aa([a,b],[(c,cc),(a,aa),(b ,bb),(a,aa2)],X)。 X = [aa,bb]; X = [aa2,bb]; 錯誤。' 如果你想要像'[aa,bb,aa2]'這樣的單一解決方案,它會更復雜一些,但應該使用'select/3'而不是'member/2'來實現,如你所提到的那樣進行遞歸調用,並在結果上調用「append/3」。 –