简体   繁体   English

列出在Prolog列表中找到的数字

[英]Make a list of numbers found in list in Prolog

I am trying to construct a list in Prolog for every number it has found. 我正在尝试在Prolog中为找到的每个号码构建一个列表。 For example, findNumber([g,o,o,d,j,0,6],[0,6]) , but I can't construct the list with the given code: 例如, findNumber([g,o,o,d,j,0,6],[0,6]) ,但是我无法使用给定的代码构造列表:

isNum(6).
isNum(6).

findNumber([],[]).
findNumber([V|T],[-|TAfter]) :-
  isNum(V),
  findNumber(T,TAfter).
findNumber([H|T],[H|TAfter]) :-
  not(isNum(H)),
  findNumber(T,TAfter).

Please help... I am in quite the pickle. 请帮忙...我很腌。 Thank you! 谢谢!

There are a few problems with your code: 您的代码存在一些问题:

You use a predicate isNum you define yourself, but only 6 seems to be a number. 您使用谓词isNum定义自己,但似乎只有6个数字。 0 is not a number? 0不是数字吗? So correct this to: 因此,请更正为:

isNum(0).
isNum(6).

or use 's builtin predicate number/1 . 或使用的内置谓词number/1 (mind using number/1 slightly modifies the semantics since number/1 does not instantiate the given variable; as long as you use the predicate in only one direction - list to sublist - and do not use uninstantiated variables, that's fine however). (使用number/1想法会稍微修改语义,因为number/1不会实例化给定的变量;只要您仅在一个方向上使用谓词-从列表到子列表-且不使用未实例化的变量,那很好)。

Secondly the predicate itself. 其次,谓词本身。 First of all, you somehow swapped the cases: here it will add the H to the resulting list in the third clause (where H is not a number). 首先,您以某种方式交换了大小写:在这里它将H添加到第三子句中的结果列表中(其中H不是数字)。 Furthermore in the second clause you add a dash ( - ) to the list (this does not seem to be the desired behavior). 此外,在第二个子句中,您在列表中添加了破折号( - )(这似乎不是所希望的行为)。 A better predicate is therefore probably: 因此,更好的谓词可能是:

findNumber([],[]).
findNumber([H|T],[H|TAfter]) :-
  number(H),
  findNumber(T,TAfter).
findNumber([H|T],TAfter):-
  not(number(H)),
  findNumber(T,TAfter).

Or you can make the predicate more compact (and a bit faster) by using a cut ( ! ): 或者,您可以使用cut( ! )使谓词更紧凑(并且更快一点):

findNumber([],[]).
findNumber([H|T],[H|TAfter]) :-
  number(H),
  !,
  findNumber(T,TAfter).
findNumber([_|T],TAfter):-
  findNumber(T,TAfter).

Demo ( swipl ): 演示( 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].

Recursive list structure 递归列表结构

In case you want to do this recursively, you could do this by extending the predicate to a three arguments version findNumber/3 . 如果您要递归执行此操作,可以通过将谓词扩展为三个参数版本findNumber/3来执行此操作。 First we map the version with two arguments findNumber/2 on findNumber/3 : 首先,我们在findNumber/3上使用两个参数findNumber/2映射版本:

findNumber(A,B) :-
    findNumber(A,B,[]).

(the previously defined predicate should be removed). (应删除先前定义的谓词)。

Next we define the following clauses: 接下来,我们定义以下子句:

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).

This works with a technique called difference lists which will be rather memory and cpu efficient. 这与称为差异列表的技术一起使用,该技术将在内存和CPU效率方面相当高。 Furthermore the call stack will only grow in the number of levels of the given list. 此外,调用堆栈只会增加给定列表的级别数。

The third argument specifies which value should be put at the tail of the list. 第三个参数指定应将哪个值放在列表的末尾。 Evidently the base case is that the list should end with a [] (that's what we do with the findNumber/2 to findNumber/3 conversion. 显然,基本情况是列表应该以[]结尾(这就是我们使用findNumber/2findNumber/3转换。

There is a special case in which Prolog will wonder whether there is a sublist (the second clause), it will call findNumber/3 with the head of the list findNumber(H,TA,TL) and will generate a list TA leaving the tail TL open. 在特殊情况下,Prolog会怀疑是否存在子列表(第二个子句),它将以列表findNumber(H,TA,TL)的开头调用findNumber/3 ,并生成列表TATL打开。 The new tail TL will than later be filled with a call findNumber(H,TL,TT) (we thus will put our original tail TT at the real back, but need an intermediate tail TL ). 新的尾部TL随后将被一个调用findNumber(H,TL,TT)填充(因此findNumber(H,TL,TT)我们会将原始的尾部TT放在真实的后面,但需要一个中间尾部TL )。

Demo ( swipl ) : 演示( 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].

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM