list Prolog:检查某项是否是列表中的最后一项?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21694499/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 02:08:37  来源:igfitidea点击:

Prolog: Checking if something is the last item in the list?

listprologdcg

提问by user3295806

I am new to prolog and am basically trying to write a clause that would evaluate as true if a given item is the last item in a given list. Here is what I have:

我是 prolog 的新手,基本上是在尝试编写一个子句,如果给定的项目是给定列表中的最后一个项目,则该子句将评估为真。这是我所拥有的:

last(X,[Y|X]).
last(X,[Y|Z]) :- last(X,Z).

I thought this would do the trick, but when I ask prolog:

我认为这可以解决问题,但是当我问序言时:

?- last(c,[a,b,c]).

Prolog returns false. I tried the following query to see what Prolog thinks should fit my definition of last:

Prolog 返回 false。我尝试了以下查询以查看 Prolog 认为应该符合我对 last 的定义的内容:

?- last(c,X).
X = [_G530|c] ;
X = [_G530, _G533|c] ;
X = [_G530, _G533, _G536|c]

So, what I am not sure about is why the "|" symbol is still in the list?

所以,我不确定的是为什么“|” 符号仍在列表中?

Update: last([c],[a,b,c]) produces the desired behavior. However, I'm not sure why my 1st argument has to be a list?

更新:last([c],[a,b,c]) 产生所需的行为。但是,我不确定为什么我的第一个参数必须是列表?

回答by traitor

You might want this:

你可能想要这个:

 last(X,[X]).
 last(X,[_|Z]) :- last(X,Z).

The |denotes a 'tail' or 'the rest of the list.'

|表示一个“尾巴”或“列表的其余部分。”

With ?- last(c,X).Prolog produces lists (according to your first definition) that have c as the last item.

使用?- last(c,X).Prolog 生成列表(根据您的第一个定义),其中 c 作为最后一项。

When you query ?- last(c,[a,b,c])., it returns false because you haven't defined a case for a list of only one item [X]or [X|[]]. So it fails when list is shorter than two items.

当您查询时?- last(c,[a,b,c]).,它返回 false,因为您还没有为只有一个项目[X]或的列表定义案例[X|[]]。所以当列表短于两个项目时它会失败。

However, last([c],[a,b,c])succeeds because you get [b|_29]or whatever denoting that the tail part might be any list. So it '_29' can be '[c]', satisfying the first definition like last([c],[b|[c]]).Remember that a nonempty list in Prolog is actually a pair of the first list item (head) and a list of the rest (tail). Usually written as [head|tail].

但是,last([c],[a,b,c])成功是因为您得到[b|_29]或表明尾部可能是任何列表的任何内容。所以它 '_29' 可以是 '[c]',满足第一个定义就像last([c],[b|[c]]).记住 Prolog 中的非空列表实际上是一对第一个列表项(头)和一个列表项(尾)。通常写作[头|尾]。

回答by false

Why not view things from a grammatical viewpoint. So what is the last element in a list?

为什么不从语法的角度来看待事物。那么列表中的最后一个元素是什么?

last(X, Xs) :-
   phrase( ( ..., [X] ), Xs).

... --> [] | [_], ... . % any sequence

回答by Dylon Dickinson

Why not just use append?

为什么不直接使用 append 呢?

last(X,Y) :-
    append(_,[X],Y).

http://www.swi-prolog.org/pldoc/man?predicate=append/3

http://www.swi-prolog.org/pldoc/man?predicate=append/3

回答by SQB

Because the tail of a list is a list itself.

因为列表的尾部是列表本身。

A list in Prolog can be seen as [H | T], where His the first element (the head), and T(the tail) is a listof all other elements.

在Prolog中的列表可以被视为[H | T],在这里H是第一个元素(头),和T(尾部)的列表的所有其它元件。

Your list [a, b, c]is actually [a | [b | [c | [] ] ] ]when you decompose it (the last tail is always an empty list):

你的列表[a, b, c]实际上是[a | [b | [c | [] ] ] ]当你分解它时(最后一个尾巴总是一个空列表):

List: [a, b, c]   Head: a   Tail: [b, c]
List: [b, c]      Head: b   Tail: [c]
List: [c]         Head: c   Tail: []

So when you get to the point where you're asking if last(c, [b, c]), that decomposes to last(c, [b|[c]]), which is why the first clause can't be instantiated, because Xcan't be both cand [c]. That is why it didwork when you asked last([c],[a,b,c]).

因此,当您问到 if 时last(c, [b, c]),它会分解为last(c, [b|[c]]),这就是为什么不能实例化第一个子句的原因,因为X不能同时是c[c]。这就是为什么当你问它时它确实有效last([c],[a,b,c])

The version proposed by alphaworks, because it takes this into account:

alpha 提出版本有效,因为它考虑到了这一点:

% A list ends with an element if contains exactly that element.
last(X,[X]).

% A list ends with an element if its tail ends with that element.
% (Since we don't care about the head, we use an underscore).
last(X,[_|T]) :- last(X,T).