在Prolog中,假设我有一个列表,例如
[fun, joke1, joke2, fun, joke3, fun, joke4, joke5, joke6]
我正在尝试构建一个列表,列表将导致
[ [joke1, joke2], [joke4, joke5, joke6] ]
使用fun作为分隔符并忽略长度为1的构建列表,因此
[joke3]
不在该列表中。
我尝试使用split_string,但它不适用于我需要获取的内容。我也尝试使用append进行递归但是也没有用。希望我能指出正确的方向。
谢谢!
答案 0 :(得分:3)
这是一个使用两个谓词的解决方案:
split_on_delimiter(L, D, S) :-
split_on_delimiter_(L, D, R),
findall(X, (member(X, R), length(X,Length), Length > 1), S).
split_on_delimiter_([], _, [[]]).
split_on_delimiter_([D|T], D, [[]|T2]) :-
split_on_delimiter_(T, D, T2).
split_on_delimiter_([H|T], D, [[H|T2]|T3]) :-
dif(H, D),
split_on_delimiter_(T, D, [T2|T3]).
split_on_delimiter_/3
是基于分隔符D
真正拆分列表的谓词。 split_on_delimiter/3
是您要调用的谓词,而后者将调用split_on_delimiter_/3
。
要仅保留长度超过1的子列表,我们使用findall
查找包含Length > 1
的拆分结果的所有子列表。
split_on_delimiter_/3
本身很简单:
dif(H, D)
)时,我们将该元素放在第一个子列表的开头并进行递归调用。?- split_on_delimiter([fun, joke1, joke2, fun, joke3, fun, joke4, joke5, joke6], fun, Z).
Z = [[joke1, joke2], [joke4, joke5, joke6]] ;
false.
split_on_delimiter_/3
有无关的选择点(这就是为什么你可以在第一个结果后按;
,因为它认为可以有更多的答案,但没有答案)。您可以使用!
或once
解决此问题。
删除这些选择点的更好解决方案是使用module(reif)
的if_/3
和(=)/3
(虽然我怀疑这对您有用):
split_on_delimiter_(L, D, [L2|T2]) :-
if_(L = [],
[L2|T2] = [[]],
( L = [H|T],
if_(H = D,
( L2 = [],
split_on_delimiter_(T, D, T2)
),
( L2 = [H|T3],
split_on_delimiter_(T, D, [T3|T2])
)
)
)
).