如果我有一个像[atm(abd,bubu,ha), atm(aei),atm(xyz,huhu), atm(aabb,a,e,x)]
这样的列表,我怎么能迭代'通过其中一个atm
结构的元素?
例如,对于atm(abd, bubu, ha)
,我想write
abd
,bubu
和ha
。
问题是结构的长度可变。
有没有办法将结构转换为列表?感谢。
答案 0 :(得分:3)
(=..)/2
@TopologicalSort已经给出了一个很好的答案,使用(=..)/2
将一个术语转换为列表的仿函数和参数。
这显然可以很好地解决当前的问题。
然而,它也有其自身的缺点:首先,最重要的是,(=..)/2
不是一般关系。例如,我们有:
?- X =.. Y. ERROR: Arguments are not sufficiently instantiated
这意味着我们无法将此构造用于生成解决方案。如果它的参数被充分实例化,它只能 。
其次,使用(=..)/2
还带来时间和内存开销,用于构建和表示列表以及到已存在的术语不同的形式。 (并且,比照变通,当然也是另一个方向。)
因此,值得一提的是:有不同的方法可以解决这个问题吗?它们更适合吗?
我如何转换你?让我数一下。
从您引用的示例中,我们必须能够按照以下形式的外观顺序处理:
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生成生成子句。)
判断列表是否是合适的数据结构有几个众所周知的标准。例如:
只有你可以针对你的特定用例回答这个问题,所以我只展示可以的样子:假设你代表你的整个初始列表如下:
[[abd,bubu,ha],[aei],[xyz,huhu],[aab,a,e,x]]
然后整个问题甚至不会出现,因为元素已经已经指定为列表。因此,不再需要转换任何东西。
答案 1 :(得分:2)
不确定
如果First
为atm(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。