2008-11-18 22 views
15

Tôi hiện đang làm việc trên một dự án rất ngắn trên Prolog, và chỉ gặp khó khăn khi cố gắng áp dụng "bộ lọc" mà tôi đã tạo vào danh sách. Tôi có những gì bạn có thể gọi là bộ lọc đã sẵn sàng, nhưng tôi không thể áp dụng nó. Sẽ tốt hơn nếu tôi minh họa:Prolog: Lọc danh sách?

filter(A, B) 

... kết quả 'đúng' nếu đáp ứng các điều kiện nhất định.

filterList(A, [X, Y, Z]) 

... ra một danh sách bao gồm tất cả các yếu tố từ đối số thứ hai mà làm cho sản lượng lọc sai. (Vì vậy, nếu bộ lọc (A, X) là đúng, đầu ra là [Y, Z]).

Tôi có chức năng "bộ lọc" sẵn sàng, nhưng bây giờ tôi cần áp dụng nó vào danh sách như được hiển thị trên ví dụ thứ hai, loại trừ tất cả các phần tử mà bộ lọc trả về true khi được áp dụng với đối số đầu tiên.

Vì vậy, nếu bộ lọc là A == B đơn giản, chức năng được cho là nhận A [A, B, A, C, D, A] và đầu ra [B, C, D], đã xóa tất cả các yếu tố mà bộ lọc áp dụng, rõ ràng.

Tôi đang gặp sự cố với cấu trúc cơ bản của hàm, vì vậy nếu có ai đó có thể cung cấp phác thảo cơ bản cho một chức năng như vậy, nó sẽ giúp ích rất nhiều. Tôi đã đơn giản hóa tình huống của mình càng nhiều càng tốt để tôi có thể lấy bất cứ điều gì bạn có thể cung cấp và sửa đổi nó cho các nhu cầu của tôi.

Cảm ơn trước!

Trả lời

11

Nếu bạn đang tìm kiếm chức năng bậc cao trong Prolog, bạn chắn nên tham khảo Naish (1995), một rất tốt tài nguyên về điều này.

định nghĩa của filter/3 của ông là như sau (ông sử dụng sự khác biệt-danh sách ký hiệu, do đó thoát cần phải xác định filter/4):


filter(_,[],[]). 
filter(P, A0-As0, As) :- 
    (
     call(P, A0) -> As = A0-As1 
    ; 
     As = As1 
    ) 
    , filter(P, As0, As1). 

Tôi có thắc mắc về ngữ này, xin hỏi tôi trong các bình luận . Đọc giấy cũng rất khuyến khích, nó cũng definess map, foldrcompose! Lưu ý rằng nhiều hạn chế mà anh ta đề cập (ví dụ: thiếu call/3 hoặc đơn đặt hàng cao hơn apply không áp dụng nữa. SWI-Prolog có nhà điều hành =.., giải quyết tất cả các mối quan tâm của mình và làm cho logic bậc ba tùy ý.

+1

Pitty Naish đề xuất áp dụng/3 trong kết luận của mình, nhưng tôi đoán cách hiện tại để đi là sử dụng cuộc gọi/n. áp dụng/3 chỉ đơn giản là gọi/3. –

+2

Xem phần thảo luận tại sao Tài liệu tham khảo Naish bị tranh chấp: http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/naish.html –

0

Vâng, bạn biết gì tôi đã chỉ ra điều đó. Vì vậy, đây là tôi gửi một câu trả lời cho câu hỏi của riêng tôi, như mong đợi một chức năng thực sự ngắn đã làm các công việc:

filterList(_,[],R,R).   % Returns answer when the list is exhausted. 
filterList(L,[A|List],Temp,Res) :- 
    filterList(L,List,New,Res), % Recursive call, New is either the same list 
    ( filter(L,A),    % in case the filter outputs true, or the list 
     New = Temp 
    ; New = [A|Temp]   % plus the current element otherwise. 
    ). 
+1

Phiên bản này luôn thành công cho bất kỳ danh sách nào. Dự định? – false

7

SWI-Prolog cung cấp exclude/3 và khác như meta-vị từ vấn đề ban đầu của bạn có thể được mã hóa như thế này:. Ví dụ

are_identical(X, Y) :- 
    X == Y. 

filterList(A, In, Out) :- 
    exclude(are_identical(A), In, Out). 

Cách sử dụng:

?- filterList(A, [A, B, A, C, D, A], Out). 
Out = [B, C, D]. 
+0

bao gồm (<(5), [3,4,5,6 , 7], Như). hoạt động giống như bộ lọc (<(5), [3,4,5,6,7], As). loại trừ là nghịch đảo ở chỗ nó cho kết quả tương tự như bộ lọc (> = (5), [3,4,5,6,7], As). – joeblog

3

có một vấn đề cố hữu với các chức năng bộ lọc có tính thành công hay thất bại của một vị từ làm tiêu chí để lọc: Chương trình kết quả không còn là một chương trình đơn điệu thuần túy nữa. Do đó, nó mất tất cả các thuộc tính khai báo của nó — ý nghĩa duy nhất còn lại là một giải thích từng bước theo thủ tục.Dưới đây là một phiên bản thuần túy, reified lọc sử dụng if_/3:

tfilter(_CT_2, [], []). 
tfilter(CT_2, [E|Es], Fs0) :- 
    if_(call(CT_2,E), Fs0 = [E|Fs], Fs0 = Fs), 
    tfilter(CT_2, Es, Fs). 

Đối số đầu tiên là như vậy, một đóng/tiếp tục sẽ nhận hai đối số thêm: Các yếu tố và kết quả là giá trị thật.

=(X,X,true). 
=(X,Y,false) :- dif(X,Y). 

Bây giờ, kết quả vẫn chính xác:

| ?- tfilter(=(X),[A,B],Xs). 
B = A, 
X = A, 
Xs = [A,A] ? ; 
X = A, 
Xs = [A], 
dif(A,B) ? ; 
X = B, 
Xs = [B], 
dif(B,A) ? ; 
Xs = [], 
dif(X,A), 
dif(X,B) ? ; 
no 

Có bốn khả năng làm thế nào một danh sách của hai yếu tố có thể được lọc bởi các tiêu chí trở bằng X. Mỗi phần tử có thể bằng nhau hoặc có thể khác nhau.

Nhược điểm của phương pháp này là người ta phải cung cấp các phiên bản được sửa đổi của tất cả các tiêu chí.

0

tôi nhận được người lớn của một quốc gia // Obtengo los adultos de un Pais, Quốc gia = Pais, dân = Personas, Person = una sola Persona

habitants(USA, [juan, pedro, david]) 

adults(Adults, Country) :- 
    findall(Person, (habitants(Country,People), member(People, Person), adult(Person)), Adults) 

Đây là một bộ lọc trong prolog // Asi es un filter en prolog