2011-11-11 36 views
5

thể trùng lặp:
Prolog delete: doesn't delete all elements that unify with ElementXóa tất cả các thành viên của một danh sách mà không thống nhất trong Prolog

Trong Prolog nếu bạn viết này:

delete([(1,1),(1,2),(1,1),(3,4)],(1,_),L). 

kết quả sẽ là:

L = [ (1, 2), (3, 4)]. 

Điều bình thường vì biến _ liên kết với 1 trong phần tử đầu tiên và nó tìm kiếm thêm các phần tử (1,1) và xóa chúng.

Có cách nào để ngăn chặn sự hợp nhất này xảy ra và xóa tất cả các thành viên của biểu mẫu (1, _). Trong trường hợp đó, kết quả phải là: L = [(3, 4)].

Trả lời

3
delete_pattern([], _, []). 
delete_pattern([H|T], P, O) :- 
    ( H \= P 
    -> O = [H|O1], 
     delete_pattern(T, P, O1) 
    ; delete_pattern(T, P, O)). 

Bạn có thể muốn sử dụng vị từ khác để lọc mà sẽ cho kết quả trong ngữ nghĩa hơi khác nhau như ==/2 hoặc [email protected]=/2.

+0

trình về nguyên tắc, nhưng phá vỡ nếu mục danh sách được không đủ instantiated vào thời điểm đó 'delete_pattern/3' được chạy. – repeat

3

Đây là phiên bản khác. Trên thực tế, một tinh khiết một:

list_el_deleted([], _, []). 
list_el_deleted([X|Xs], X, Ys) :- 
    list_el_deleted(Xs, X, Ys). 
list_el_deleted([X|Xs], E, [X|Ys]) :- 
    dif(X,E), 
    list_el_deleted(Xs, E, Ys). 

Đang cố gắng nó trên truy vấn của bạn cho thấy các nguồn thực tế của sự nhập nhằng trong báo cáo vấn đề của bạn:

?- list_el_deleted([(1,1),(1,2),(1,1),(3,4)],(1,X),L). 
X = 1, 
L = [ (1, 2), (3, 4)] ; 
X = 2, 
L = [ (1, 1), (1, 1), (3, 4)] ; 
L = [ (1, 1), (1, 2), (1, 1), (3, 4)], 
dif(X, 1), 
dif(X, 2), 
dif(X, 1). 

Vì vậy, tất cả phụ thuộc vào những gì X thực sự là: 1, 2, hoặc cái gì khác. Lưu ý rằng các phiên bản trước thảo luận ở đây phụ thuộc vào instantiation thực tế mà làm cho lập luận nhiều khó khăn hơn:

?- delete([a],X, Xs), X = c. 
false. 

?- X = c, delete([a],X, Xs). 
X = c, 
Xs = [a]. 
+1

@repeat: Đặt giải pháp của bạn [tại đây] (http://stackoverflow.com/questions/8100586/prolog-delete-doesnt-delete-all-elements-that-unify-with-element#). – false

Các vấn đề liên quan