如何从序言列表中删除列表? [英] How to remove a list from a list in prolog?

查看:147
本文介绍了如何从序言列表中删除列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在序言中实现以下问题:
鉴于 L1=[1,2,3,4] and L2=[2,3,4]
调用名为remove_list(L1,L2,L)的函数将从L1中删除L2.
所以L将是[1]. 但是,如果第二个列表的元素与L1中的顺序不同,或更准确地说,第二个不是第一个列表的子集,它将不会删除任何内容.
L1=[1,2,3,4,5] and L2=[2,3,6] or L2=[2,6] or L2=[4,3,2] will result L=[1,2,3,4,5]
任何帮助将不胜感激. 预先感谢

I want to implement the following problem in prolog:
Given L1=[1,2,3,4] and L2=[2,3,4]
calling a function named remove_list(L1,L2,L) will remove L2 from L1 .
So L will be [1]. But if the elements of the 2nd list are not in the same order as in L1 or more accurately the 2nd one is not a subset of the first List ,it wont remove anything.
SayL1=[1,2,3,4,5] and L2=[2,3,6] or L2=[2,6] or L2=[4,3,2] will result L=[1,2,3,4,5]
Any help will be highly appreciated. Thanks in advance

推荐答案

您可以使用递归构建谓词remove_list/3,这是在Prolog中处理列表时非常有用的工具.

You can build your predicate remove_list/3 using recursivity, which is an useful tool when dealing with lists in Prolog.

remove_list([], _, []).
remove_list([X|Tail], L2, Result):- member(X, L2), !, remove_list(Tail, L2, Result). 
remove_list([X|Tail], L2, [X|Result]):- remove_list(Tail, L2, Result).

咨询:

?- remove_list([4,5,1,6,3], [1,4,7], L).
L = [5, 6, 3].

这个想法是将原始列表"L1"中的每个元素复制到最终列表"L"中,除非该元素是第二个列表"L2"的成员.
您的基本子句是您的停止条件,当原始列表"L1"为空时,如果忽略列表"L2",则结果始终是相同的空列表. (您不能从空白列表中删除任何内容.)
您的第二个子句,如果头部中的元素是列表"L2"的成员,则不要将列表"L1"的头部中的元素复制到最终列表"L",还应使用以下方式对谓词进行递归调用:您列表"L"的尾巴.
最后一个子句,将列表"L1"开头的元素复制到最终列表"L",并使用该列表"L"的尾部对谓词进行递归调用.我们在这里不需要目标member/2,因为我们在上一个子句中使用了cut.

The idea is to copy every element in your original list "L1" to your final list "L", except when that element is member of the second list "L2".
Your base clause is your stop condition, when your original list "L1" is empty, in that case ignoring your list "L2", the result is always the same empty list. (You can't delete nothing from the empty list).
Your second clause, don't copy the element in the head of the list "L1" to the final list "L" if that element in the head is member of the list "L2", also make the recursive call to the predicate with the Tail of your list "L".
And the final clause, copy the element in the head of the list "L1" to the final list "L", and also make the recursive call to the predicate with the Tail of that list "L". We don't need the goal member/2 here, because we used a cut in the previous clause.

编辑:仅当您想从"L2"列表中包含的列表"L1"中删除项目时,才考虑此答案,而与顺序无关.要从集合"L1"中删除子集"L2",请使用 Lurker解决方案或其他解决方案:

This answer should only be considered if you want to remove items from the list "L1" contained in the "L2" list, regardless of the order. To remove the subset "L2" from set "L1", please use Lurker's solution or this other solution:

remove_list(L, [], L):- !.
remove_list([X|Tail], [X|Rest], Result):- !, remove_list(Tail, Rest, Result).
remove_list([X|Tail], L2, [X|Result]):- remove_list(Tail, L2, Result).

此新解决方案考虑了列表"L2"中元素的顺序,但并非严格意义上,即可以散布在原始列表"L1"中,这并不违反"L2"是"L1"的子集.

This new solution considers the order of the elements in list "L2", but not in the strict sense, ie, may be interspersed in the original list "L1", which does not violate the concept of "L2" being a subset of "L1".

[2,4]是集合[1,2,3,4,5,6]的子集,但[2,4,7]不是:

[2,4] is a subset of the set [1,2,3,4,5,6], but [2,4,7] is not:

?- remove_list([1,2,3,4,5,6], [2,4], L).
L = [1, 3, 5, 6].

?- remove_list([1,2,3,4,5,6], [4,2], L).
false.

?- remove_list([1,2,3,4,5,6], [2,4,7], L).
false.

现在,考虑到需要获得原始集合而不是否定响应(如果可以删除原始集合中的任何元素的事实),那么我们使用辅助谓词:

Now, given the fact that is desired to obtain the original set rather than the negative response in case that any of the elements from the original set can be removed, then we use an auxiliary predicate:

rm_subset(L1, L2, L):-  remove_list(L1, L2, L),!.
rm_subset(L1, L2, L1).

咨询:

?- rm_subset([1,2,3,4,5,6], [4,2], L).
L = [1, 2, 3, 4, 5, 6].

?- rm_subset([1,2,3,4,5,6], [2,4], L).
L = [1, 3, 5, 6].

这篇关于如何从序言列表中删除列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆