如何遍历结构?



如果我有一个列表,例如:[atm(abd,bubu,ha), atm(aei),atm(xyz,huhu), atm(aabb,a,e,x)],我如何"迭代"atm结构之一的元素?

例如,对于atm(abd, bubu, ha),我想writeabdbubuha

问题是结构的长度是可变的。

有没有办法将结构转换为列表?谢谢。

使用(=..)/2

@TopologicalSort已经给出了一个很好的答案,使用(=..)/2将项转换为函子和参数列表

这显然非常普遍地解决了眼前的问题。

然而,它也有自己的缺点:首先,也是最重要的是,(=..)/2是一个一般的关系。例如,我们有:

?- X =.. Y.错误:参数未充分实例化

这意味着我们不能使用此构造来生成解决方案。当其参数被充分实例化时,它才有效。

其次,使用(=..)/2还伴随着构建和表示列表的时间和内存开销以及已经以不同 形式存在的术语。(而且,比照 ,当然也是在另一个方向。

因此,可能值得一问:是否有不同的方法来解决此任务?它们更适合吗?

备选方案1:手动操作

我如何转换你?让我数数方法。

从您引用的示例来看,我们必须能够按照其出现的顺序处理以下形式的术语:

  • atm/3
  • atm/1
  • atm/2
  • atm/4

这里的要点是显示的情况数量是有限的,因此我们可以轻松地像这样处理它们:

atm_list(ATM(A), [A])。 atm_list(自动取款机(A,B), [A,B])。 atm_list(ATM(A,B,C), [A,B,C])。 atm_list(ATM(A,B,C,D), [A,B,C,D])。

要转换此类术语的列表,您可以使用maplist/2

?- Ls = [atm(abd,bubu,ha), atm(aei),atm(xyz,huhu), atm(aabb,a,e,x)],  maplist(atm_list, Ls, Lists). Ls = [atm(abd, bubu, ha), atm(aei), atm(xyz, huhu), atm(aabb, a, e, x)],列表 = [[abd, bubu, ha], [aei], [xyz, huhu], [aabb, a, e, x]]。

一个主要的优点是这种关系非常通用,也可以用来生成答案:

?- atm_list(A, Ls).A = atm(_27464, _27466, _27468), Ls = [_27464, _27466, _27468] ; A = atm(_27464), Ls = [_27464] ; A = atm(_27464, _27466), Ls = [_27464, _27466] ; A = atm(_27464, _27466, _27468, _27470), Ls = [_27464, _27466, _27468, _27470]。

这也比使用(=..)/2更有效。显然,只有在出现的案件数量有限的情况下才能这样做。(练习:编写一个为所有整数 1..N生成子句的 Prolog 程序)。

备选方案 2:使用列表

有几个众所周知的标准来判断列表是否是适当的数据结构。例如:

  • 空列表在您的用例中有意义吗?
  • 所有可能的长度都有合理的案例吗?
  • 等。

对于您的特定用例,只有您可以回答这个问题,因此我只展示它的外观: 假设您按如下方式表示整个初始列表:

[[
abd,bubu,ha],[aei],[xyz,huhu],[aab,a,e,x]]

然后整个问题甚至不会出现,因为元素已经指定为 列表。因此,不再需要转换任何东西。

当然。

如果Firstatm(abd,bubu,ha)(例如),此代码会将其拆分为您可以浏览的列表。

First =.. List.

然后,List将被[atm, abd, bubu, ha].

IDK,如果这适用于您的特定版本的PROLOG。 我正在使用SWI-PROLOG。 如果没有,也许您的版本具有类似的谓词。

有关详细信息,请参阅 http://www.swi-prolog.org/pldoc/doc_for?object=(%3D..)/阿拉伯数字。

最新更新