如何遍历结构?

时间:2017-03-22 20:08:39

标签: prolog

如果我有一个像[atm(abd,bubu,ha), atm(aei),atm(xyz,huhu), atm(aabb,a,e,x)]这样的列表,我怎么能迭代'通过其中一个atm结构的元素?

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

问题是结构的长度可变。

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

2 个答案:

答案 0 :(得分:3)

使用(=..)/2

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

这显然可以很好地解决当前的问题。

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

?- X =.. Y.
ERROR: Arguments are not sufficiently instantiated

这意味着我们无法将此构造用于生成解决方案。如果它的参数被充分实例化,它只能

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

因此,值得一提的是:有不同的方法可以解决这个问题吗?它们更适合吗?

备选方案1:手动执行

  

我如何转换你?让我数一下。

从您引用的示例中,我们必须能够按照以下形式的外观顺序处理:

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

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

atm_list(atm(A),       [A]).
atm_list(atm(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)],
Lists = [[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 更高效。显然,只有在出现的案例数量有限时才能这样做。 (练习:编写一个Prolog程序,为所有整数1..N生成生成子句。)

备选方案2:使用列表

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

  • 空列表在您的用例中是否有意义?
  • 是否有所有可能长度的明智案例?

只有你可以针对你的特定用例回答这个问题,所以我只展示可以的样子:假设你代表你的整个初始列表如下:

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

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

答案 1 :(得分:2)

不确定

如果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..)/2