我需要构建一个带有“循环”的新列表。基本上我不能显式使用递归,所以我使用append来查看列表列表。
我可以得到这个元素。问题是我需要检查这个元素,如果有什么是真的,它返回我需要放回列表中的另一个元素。它确实正确检查并正确更改。
我遇到的问题是如何创建一个全新的列表。
所以,如果我有
[[1,1,1],[2,6,2],[3,3,3]]
我浏览了每个元素。说我到了6,它改变了。所以我需要创建一个像这样的新列表,
[[1,1,1],[2,10,2],[3,3,3]].
现在我的主要问题是创建每一行。如果我可以创建每一行,我将能够创建一个列表列表。
所以要稍微打破这个,让我们担心[1,1,1]。
我在将新元素追加到新列表的同时浏览每个元素。新名单现在是[1,1,1]
我有这个:
set(Row,Col,Bin,TheEntry,Bout) :-
append(ListLeft, [R|_], Bin),
append(ListLeft2, [C|_], R),
length(ListLeft, LenR),
length(ListLeft2,LenC),
CurrRow is LenR + 1,
CurrCol is LenC + 1,
getChar(C, Row, Col, CurrRow, CurrCol,TheEntry, NewC),
appendhere?.
我需要在那里创建一个新列表,其中包含从NewC返回的字符。不知道怎么做。
任何线索?
感谢。
答案 0 :(得分:2)
为了让您了解如何使用append/3
从列表列表中提取项目,请考虑以下名为replace/2
的谓词:
replace(In, Out) :-
append(LL, [L|RL], In),
append(LE, [E|RE], L),
replaceElement(E, NewE), !,
append(LE, [NewE|RE], NewL),
append(LL, [NewL|RL], Out).
replace(In, In).
这个非递归谓词,如In
一样,列出一个列表,并在内部列表E
中找回元素L
的回溯可以通过replaceElement/2
替换;如果是这样,则首先构造内部列表(NewL
)替换它,然后在构造新外部列表(Out
)时使用此新列表作为结果。
注意这只是为了演示如何使用append/3
拆分列表列表,以便在需要时通过回溯而不是递归来检索单个元素,如请求的。一旦E
NewE
通过replaceElement/3
找到了append/3
可替换的元素,就可以使用replace/2
再次使用它来构建列表,如图所示。
另请注意,此建议(旨在帮助您,而不是您的最终答案)也恰好只替换内部列表中的单个元素(如果有的话)。如果您想在使用此技术的assert
或类似的单个调用中对输入列表进行多次替换,那么您几乎肯定需要一个递归定义,或者能够使用全球数据库通过replace/2
。如果其他人可以提供定义作为反例,我很乐意予以纠正。
使用此示例谓词replaceElement(6, 10).
,以及以下事实:
1 ?- replace([[1,1,1],[2,6,2],[3,3,3]], Out).
Out = [[1, 1, 1], [2, 10, 2], [3, 3, 3]] ;
false.
执行以下操作可为您提供所需的行为:
!
如果你不能使用cut(replace(In, In)
),可以省略它,但请注意第二个句子replace/2
将导致对replace/2
的所有调用至少回溯一次给你输入列表。如果不希望出现这种情况,如果没有替换,则省略第二个子句会导致{{1}}彻底失败。
答案 1 :(得分:0)
如果您不能使用递归并且必须使用回溯来执行此操作,则应执行以下操作: 假设Bin是一个列表列表(每个项目是一个完整的行) 〜将输入Bin拆分为三个部分(“左”行列,行和剩余行列表)。这可以使用append / 3来完成,例如append(Left,[Item | Rest],Rows) 〜现在获得'左'行的长度 〜使用'is'运算符测试长度,检查左侧列表是否包含第1行 〜同样但现在使用Item,即将它分成三部分(LeftColums,ColumItem和Rest) 〜现在测试所需列的长度 〜现在您要更改项目,所以您需要做的就是使用两个附加重建列表(一个用于重建所选行,另一个用于重建输出列表)。
因此,从您的代码中,您不会使用未命名的变量(_)。而不是必须使用命名变量来重建项目的新列表。