从 Prolog 中的列表中删除头部

Removing heads from lists in Prolog

我正在尝试编写一个谓词以从列表列表中的每个列表中删除头部并将尾部添加到新列表中。结果列表应作为第二个参数返回。

这是尝试:

construct_new(S,New) :-
    New = [],
    new_situation(S,New).

new_situation([],_).
new_situation([H|T], New) :-
    chop(H, H1),
    new_situation(T, [H1|New]).

chop([_|T], T).

你可以这样称呼它:

construct_new([[x,x],[b,c],[d,e,f]],S).

然而,这只会产生输出 true.

分步执行

  1. 您的查询是 construct_new(Input,Output),用于一些实例化的 Input 列表。
  2. construct_new/2 中的第一个语句将 Output (a.k.a. New) 与空列表统一起来。 返回的列表应该在哪里可供调用者使用?两个论点现在统一了。
  3. 你打电话给new_situation(Input,[])
  4. 您匹配第二个子句 new_situation([H|T],[]),它递归地执行它的任务(第 4 步,...),直到...
  5. 您到达 new_situation([],_)成功 丢弃您构建的中间列表。

解决方案

  • 写一个简单的递归谓词:

    new_situation([],[]).
    new_situation([[_|L]|T],[L|R]) :-
        new_situation(T,R).
    
  • 使用maplist:

    construct_new(S,R) :-
        maplist(chop,S,R).
    

备注

正如其他答案和评论所指出的,您的谓词命名有误。 construct_new 不是关系,而是动作,几乎可以用来表示任何东西。我倾向于喜欢 chop 因为它清楚地传达了斩首的行为,但这不是一个合适的关系名称。 repeatlist_head_tail(L,H,T) 是声明式的,并将变量与其角色相关联。当使用 maplist 时,另一个谓词 (new_situation) 甚至不需要存在...

...虽然guillotine/3很诱人

我们将 maplist/[3-4] 与以下辅助谓词之一一起使用:

list_tail([_|Xs],Xs).

list_head_tail([X|Xs],X,Xs).

让我们运行一些查询!

?- maplist(list_head_tail,[[x,x],[b,c],[d,e,f]],Heads,Tails).
Heads = [x,b,d],
Tails = [[x],[c],[e,f]].

如果您对尾巴感兴趣,请将maplist/4list_head_tail/3一起使用...

?- maplist(list_head_tail,[[x,x],[b,c],[d,e,f]],_,Tails).
Tails = [[x],[c],[e,f]].

... 或者,更简单,maplist/3list_tail/2:

?- maplist(list_tail,[[x,x],[b,c],[d,e,f]],Tails).
Tails = [[x],[c],[e,f]].

你也可以使用有点难看的单线 findall/3:

?- L = [[x,x],[b,c],[d,e,f]],
   findall(T, ( member(M, L), append([_], T, M) ), R).
R = [[x], [c], [e, f]].

(好的,从技术上讲是两行代码。无论哪种方式,您甚至不需要定义辅助谓词。)

但绝对更喜欢使用 chopmaplist 解决方案,如图

如果您手动进行地图列表扩展,并将您的 chop/2 命名得更好一些,您将得到:

lists_tails([], []).
lists_tails([X|Xs], [T|Ts]) :-
    list_tail(X, T),
    lists_tails(Xs, Ts).

并且由于您可以在谓词的头部进行统一,因此您可以将其转换为:

lists_tails([], []).
lists_tails([[_|T]|Xs], [T|Ts]) :-
    lists_tails(Xs, Ts).

但这与您在其他答案中的相同。

练习:为什么我们不能说:

?- maplist(append([_]), R, [[x,x],[b,c],[d,e,f]]).

这可以用 DCG 来完成:

owth(Lists, Tails) :-
    phrase(tails(Tails), Lists).

tails([]) --> [].
tails([T|Tails]) --> [[_|T]], tails(Tails).

生成这些查询:

| ?- owth([[x,x],[b,c],[d,e,f]], T).

T = [[x],[c],[e,f]] ? ;

no
| ?- owth(L, [[x],[c],[e,f]]).

L = [[_,x],[_,c],[_,e,f]]

yes

(owth = 头朝下! 或者,如果使用另一个方向,头朝上! )

如果你也想抓人头,可以按如下方式增强:

owth(Lists, Heads, Tails) :-
    phrase(tails(Heads, Tails), Lists).

tails([], []) --> [].
tails([H|Hs], [T|Tails]) --> [[H|T]], tails(Hs, Tails).