2013-02-11 149 views
3

我正在开发用Prolog编写的应用程序。我得到了一个要过滤元素列表并删除那些不符合特定约束或条件的元素,并保持原始列表顺序的问题。我认为最好的方式做这将是这样的:在Prolog中筛选列表

filter([],Filtered). 
filter([L|List],[F|Filtered]) :- 
    /* Conditions are met: bypass the element to the filtered list */ 
    check_conditions(L), 
    filter(List,Filtered). 
filter([L|List],Filtered) :- 
    /* Conditions are not met: do not include the element in the filtered list */ 
    filter_aborts(List,Filtered). 

接受它作为一个解决我的问题,我想试试看(独立)之前,所以我编译和运行我的代码(SWI -Prolog)并测试了几种情况。当我使用硬编码列表中的Prolog键入查询(或任何你想将它命名),我得到了这样的事情:

?- filter([id01,id02,id03,id04,id05,id06],F). 
F = [id03, id05, id06|_G1024] . 

肯定是过滤列表,但我得到这个实例名称“_G1024”在它的结尾。我知道这是因为F没有实例化,但我不知道解决方案是什么。此外,如果我尝试做一些像进入清单作为一个实例化的变量不同,我所得到的是更奇怪:

?- L=[id02,id03,id04,id05,id06]. 
L = [id02, id03, id04, id05, id06]. 

?- filter(L,F). 
L = [] ; 
L = [id01], 
F = [id01|_G347] ; 
L = [id01, id01], 
F = [id01, id01|_G403] 
... and so on. 

应该是分配一次变量不是Prolog的变量?我的程序实际上是否改变了L或者我没有正确理解它?除此之外,由于我是Prolog新手,因此对于我的序言-let的说法 - “风格”,我将不胜感激。

回答

4

你的基地递归应该写

filter([],[]). 

,你有一个错字

filter([L|List],[L|Filtered]) :- 
... 

代替(第二)长,你有单˚F

+0

我刚刚发表评论当我阅读您的答案时发现(愚蠢)错误。非常感谢,那是错误!即使如此,解释第二个错误是什么? – 2013-02-11 14:30:01

+0

我在写下这个问题时考虑了一个错字,因为写的程序会输出一个* not instanced *变量的列表 – CapelliC 2013-02-11 15:05:07

7

您使用SWI-Prolog的,所以你可以根据你的条件编写一个成功或失败的谓词,然后使用包括(Predidate,Lst,Success)。对于axample

include(check_conditions,Lst, Success) 
+0

您是对的(+1),所提供的谓词会更好地用include/3编写,但我最终自己写了一个过滤器/ 3,因为我想(为了一点效率)能够改变接受的元素 – CapelliC 2013-02-11 14:18:52

+0

Tanks @ joel76!我不知道这个“include/3”谓词。我会在这里使用它,因为它完全符合我的需求。 – 2013-02-11 14:32:00