【发布时间】:2012-04-04 08:18:21
【问题描述】:
是否可以从 Prolog 的列表中获取所有元素?
类似:我们有 getElements([[[a,b,[c]],d,e],f,g,[h,[i,j]]],S) 结果是:S = [a,b,c,d,e,f,g,h,i,j] ...
感谢您的帮助。
【问题讨论】:
-
研究栏+“扁平化”应该会让你开心。
是否可以从 Prolog 的列表中获取所有元素?
类似:我们有 getElements([[[a,b,[c]],d,e],f,g,[h,[i,j]]],S) 结果是:S = [a,b,c,d,e,f,g,h,i,j] ...
感谢您的帮助。
【问题讨论】:
您要求列表列表中的所有元素。也就是说,对于[[1,2,3],[4]],这将是列表[1,2,3,4]。但是,对于[[[1],[3]]],这将是列表[[1],[3]],因为[1] 和[3] 是元素。出于这个原因,flatten/2 是不正确的,它给你[1,3] 作为答案。此外,对于1,它会给出[1]...
这是使用dcg的解决方案:
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
seqq([]) --> [].
seqq([Es|Ess]) --> seq(Es), seqq(Ess).
?- phrase(seqq([[[1],[3]]]), Xs).
Xs = [[1],[3]].
?- phrase(seqq(1), Xs).
false.
此解决方案现在也适用于以下情况:
?- phrase(seqq([S1,S2]), [1,2]).
S1 = [],
S2 = [1,2] ;
S1 = [1],
S2 = [2] ;
S1 = [1,2],
S2 = [] ;
false.
而flatten/2 完全错误:
?- flatten([S1,S2],[1,2]).
S1 = 1,
S2 = 2.
【讨论】:
在 SWI-Prolog(可能还有其他)中,您可以使用 flatten/2:
?- flatten([[[a,b,[c]],d,e],f,g,[h,[i,j]]], S).
S = [a, b, c, d, e, f, g, h, i|...].
请注意,the SWI-Prolog manual page for flatten/2 包含以下语句:
最终需要 flatten/3 通常表明,例如 append/3 用于附加两个列表,这是一个糟糕的设计。
但是,页面并没有说明是否有另一个原生谓词来替换它。
我相信会提供更好的答案。
【讨论】: