从Prolog列表中删除每个列表中的第一个元素的最佳方法是什么?

时间:2017-10-06 06:26:11

标签: list data-structures prolog

我正在尝试删除列表列表中每个列表的第一个元素。 例如,要列出[[1,2],[3,4]],我应该返回[[2],[4]]。 在大多数情况下,以下代码可以正常工作:

remove_firstElem([],[]). 
remove_firstElem([[_H|T]|Ls],[T|L]) :-
    remove_firstElem(Ls,L).

但对于像[[1],[2]]这样的列表,我希望它返回[]而不是[[],[]]。

到目前为止,我尝试的是:

remove_firstElem([_H|Ls],L) :-
    length(_H,1),
    remove_firstElem(Ls,L).

但它返回[ ],[[ ]],[[ ]],[[ ],[ ]],我真的不知道它有什么问题。

任何人都可以帮我解决吗?谢谢你的帮助!

2 个答案:

答案 0 :(得分:1)

如果我理解正确,你想要弹出列表的头部,但是如果列表只包含一个元素(或者根本没有),则应该删除该列表。

我们可以检查子列表是否包含至少两个带有模式的元素:

pop_lists([[_,H2|T]|TA],[[H2|T]|TB]) :-
    pop_lists(TA,TB).

所以我们在第一个列表中有一个模式[_,H2|T]_与第一个元素绑定,H2与第二个元素绑定,其余元素与尾部绑定。

无法与该模式统一的列表是空列表或包含一个元素的列表。所以在这种情况下我们完全忽略它们:

pop_lists([[]|TA],TB) :-
    pop_lists(TA,TB).
pop_lists([[_]|TA],TB) :-
    pop_lists(TA,TB).

如果我们到达列表的末尾,当然我们也将过滤器与空列表统一起来:

pop_list([],[]).

我们最好把这个子句放在第一行,使我们的谓词更加多向。总而言之,我们有以下解决方案:

pop_list([],[]).
pop_list([[_,H2|T]|TA],[[H2|T]|TB]) :-
    pop_list(TA,TB).
pop_list([[]|TA],TB) :-
    pop_list(TA,TB).
pop_list([[_]|TA],TB) :-
    pop_list(TA,TB).

我们可以进一步对语句进行重新排序,以使回溯量减少:

pop_list([],[]).
pop_list([[]|TA],TB) :-
    pop_list(TA,TB).
pop_list([[_]|TA],TB) :-
    pop_list(TA,TB).
pop_list([[_,H2|T]|TA],[[H2|T]|TB]) :-
    pop_list(TA,TB).

答案 1 :(得分:0)

更简单的方法:

list_tail([_|Es], Es).
maplist(list_tail, Input, Output).