[英]Get list of atoms by index from i to j in Prolog
我想根据给定的index_from i至index_to j从我的原子列表中获取原子列表。 我尝试了很多次,但没有返回列表,但返回了“ true”。下面是我的代码,我想念什么? 如何获取输出列表而不是“ true”。
% splitList(INPUT_LIST, INDEX_FROM, INDEX_TO, INDEX_FROM, OUTPUTLIST).
splitList(INPUT_LIST,INDEX_FROM,INDEX_TO, S,LIST) :-
INPUT_LIST = INPUT_LIST,
S = S,
INDEX_FROM =:= INDEX_TO + 1,
write(LIST),
LIST = LIST.
splitList(INPUT_LIST,INDEX_FROM,INDEX_TO,S,LIST) :-
INDEX_FROM < INDEX_TO + 1,
nth0(INDEX_FROM, INPUT_LIST, ELEMENT),
( INDEX_FROM =:= S ->
L = []
;
L = LIST
),
IF is INDEX_FROM + 1,
append([ELEMENT],L,NLIST),
splitList(INPUT_LIST,IF,INDEX_TO,S,NLIST),
!.
?- splitList(['TYPE_INT', 'IDENTIFIER', 'OPEN_P', 'TYPE_INT', 'IDENTIFIER', 'COMMA'],0,3,0,L).
?- true.
My atom list: ['TYPE_INT', 'IDENTIFIER', 'OPEN_P', 'TYPE_INT', 'IDENTIFIER', 'COMMA'],
if index_from is 1, index_to is 3, I am expecting a returned output_list:
['TYPE_INT', 'IDENTIFIER', 'OPEN_P', 'TYPE_INT'] instead of a 'true',
在我的基本情况下,“ write(LIST)会写入期望的列表”,有什么想法吗?
您可以不使用cut来编写这样的谓词。 考虑一下谓词应描述的内容:一个列表,一些起始,结束和当前位置的索引以及适合您的起始和结束索引的第一个列表的子列表。 所以list_indices_sublist可能是个好名字。 现在考虑您可能遇到的情况:
如果当前位置和结束位置相同,则第一个列表的头部是子列表中的最后一个:
list_indices_sublist([X|_Xs],_Start,End,End,[X]).
如果当前位置在开始位置和结束位置之间,则第一个列表的头部在子列表中。 对于两个列表的尾部,关系(=谓词)也必须成立(=递归):
list_indices_sublist([X|Xs],Start,End,Pos,[X|Zs]) :-
Pos #>= Start,
Pos #< End,
Nextpos #= Pos + 1,
list_indices_sublist(Xs,Start,End,Nextpos,Zs).
如果当前位置小于开始位置,则列表的头部不在子列表中。 对于尾巴,与上面相同:
list_indices_sublist([X|Xs],Start,End,Pos,Zs) :-
Pos #< Start,
Nextpos #= Pos+1,
list_indices_sublist(Xs,Start,End,Nextpos,Zs).
您可能还考虑提供一个更简洁的界面,该界面隐藏辅助变量以说明列表中的当前位置。 这样的谓词对于应满足list_indices_sublist / 5的所有三个规则的约束也将是一个好地方,例如,开始索引必须小于或等于结束索引。 我们将此谓词称为list_sublist_from_to / 4。 放在一起:
:- use_module(library(clpfd)).
list_sublist_from_to(L,S,Start,End) :-
Start #=< End,
list_indices_sublist(L,Start,End,1,S).
list_indices_sublist([X|_Xs],_Start,End,End,[X]).
list_indices_sublist([X|Xs],Start,End,Pos,[X|Zs]) :-
Pos #>= Start,
Pos #< End,
Nextpos #= Pos + 1,
list_indices_sublist(Xs,Start,End,Nextpos,Zs).
list_indices_sublist([X|Xs],Start,End,Pos,Zs) :-
Pos #< Start,
Nextpos #= Pos+1,
list_indices_sublist(Xs,Start,End,Nextpos,Zs).
关于您提供的示例:您的意思是1到4,对不对?
?- list_sublist_from_to(['TYPE_INT', 'IDENTIFIER', 'OPEN_P', 'TYPE_INT', 'IDENTIFIER', 'COMMA'] ,L,1,4).
L = ['TYPE_INT','IDENTIFIER','OPEN_P','TYPE_INT'] ? ;
no
或1到3以及在子列表中包含3个元素的答案:
list_sublist_from_to(['TYPE_INT', 'IDENTIFIER', 'OPEN_P', 'TYPE_INT', 'IDENTIFIER', 'COMMA'] ,L,1,3).
L = ['TYPE_INT','IDENTIFIER','OPEN_P'] ? ;
no
注意:如果要开始使用0而不是1来计数列表位置,只需在list_sublist_from_to / 4的第二个目标中将1更改为0
首先,您应该注意,Prolog不是基于分配,而是基于统一。 然后,例如
INPUT_LIST = INPUT_LIST,
是重言式(将同一术语本身结合在一起,始终为真)。 您可以安全地删除它们。
其次,您的代码还有一个没有明确作用的附加参数S
可能是您尝试的实现的剩余细节,但实际上应该将其“隐藏”,例如:
% splitList(INPUT_LIST, INDEX_FROM, INDEX_TO, OUTPUTLIST).
splitList(INPUT_LIST, INDEX_FROM, INDEX_TO, LIST) :-
splitList(INPUT_LIST, INDEX_FROM, INDEX_TO, 0, LIST).
第三,谓词的最后一个子句末尾的剪切是完全没有用的,因为已经尝试了所有替代方法-成功。 什么都没剪...
第四,由于您使用内置的nth0 / 3,因此请注意,更简单的实现可能是
splitList(INPUT_LIST,INDEX_FROM,INDEX_TO, LIST) :-
findall(E, (between(INDEX_FROM,INDEX_TO,I),nth0(I,INPUT_LIST,E)), LIST).
?- splitList(['TYPE_INT', 'IDENTIFIER', 'OPEN_P', 'TYPE_INT', 'IDENTIFIER', 'COMMA'],0,3,L).
L = ['TYPE_INT', 'IDENTIFIER', 'OPEN_P', 'TYPE_INT'].
但是,让我们尝试更正您的代码。 可能
splitList(INPUT_LIST,INDEX_FROM,INDEX_TO, LIST) :-
splitList(INPUT_LIST,INDEX_FROM,INDEX_TO, 0, LIST).
splitList(INPUT_LIST,INDEX_FROM,INDEX_TO, S,LIST) :-
S < INDEX_FROM,
S1 is S+1,
splitList(INPUT_LIST,INDEX_FROM,INDEX_TO, S1,LIST).
splitList(INPUT_LIST,INDEX_FROM,INDEX_TO, S,[ELEMENT|LIST]) :-
S >= INDEX_FROM, S =< INDEX_TO,
nth0(S, INPUT_LIST, ELEMENT),
S1 is S+1,
splitList(INPUT_LIST,INDEX_FROM,INDEX_TO, S1,LIST).
splitList(_INPUT_LIST,_INDEX_FROM,INDEX_TO, S,[]) :-
S > INDEX_TO.
并会获得与上面列出的基于findall / 3的单层纸类似的结果。 请注意,不是使用append / 3,而是将ELEMENT
“约束”到“输出”参数中。 查看您是否可以发现此代码固有的问题,尤其是尝试了解原因
?- splitList(['TYPE_INT', 'IDENTIFIER', 'OPEN_P', 'TYPE_INT', 'IDENTIFIER', 'COMMA'],0,10,L).
false.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.