如何解决在追加到另一个列表时迭代列表
我是 Prolog 的新手。下面的谓词应该处理一个字符串列表,每个字符串包含一个用空格分隔的名字和姓氏。它的意思是通过每个元素,用空格将其分隔为一个用于 FirstName 的元素和另一个用于 LastName 的元素,并将这些值添加到 FirstNames 列表和 LastNames 列表中。最后,它应该返回与原始列表顺序相对应的所有名字和姓氏的列表。我正在努力让它发挥作用。
populate([]).
populate([H|T],FirstNames,LastNames) :-
split_string(H," ",Elems),Elems = [FirstName,LastName],append(FirstNames,[FirstName],FirstNames2),append(LastNames,[LastName],LastNames2),populate(T,LastNames).
例如,如果给定
?- populate(["Peter Parker","Bruce Wayne"],LastNames),
它应该返回
FirstNames = ["Peter","Bruce"]
和
LastNames = ["Parker","Wayne"].
解决方法
在 SWI-Prolog 中对问题进行编码,具有以下特点:
- 使用定语从句语法将姓名分成名字和姓氏
- 利用库
dcg/basics
,更准确地说是规则nonblanks//1
和blank//0
分别处理非空白和单字符空白 - 处理文本的 SWI-Prolog DCG 假定一个 unicode-codes 列表作为输入(而不是字符列表),因此我们通过使用
atom_codes/2
来拆分和重组文本来兑现这一点- - 在整个过程中使用原子 (
'John Wayne'
) 而不是 SWI-Prolog 字符串 ("John Wayne"
) 以实现一致性。 - 使用 plunit 单元测试进行说明。
所以:
首先编写一个小谓词,使用 DCG 将“名字原子”分离成“名字原子”和“姓氏原子”:
:- use_module(library(dcg/basics)).
name(First,Last) -->
nonblanks(FirstCodes),% collect a list of codes for the first name
blank,% then comes a blank
nonblanks(LastCodes),% collect a list of codes for the last name
{ atom_codes(First,FirstCodes),% fuse the codes into a "first name atom"
atom_codes(Last,LastCodes) }. % fuse the codes into a "last name atom"
separate(Name,First,Last) :-
atom_codes(Name,NameCodes),phrase(name(First,Last),NameCodes).
separate/3
我们可以测试一下:
:- begin_tests(separate).
test(1) :-
separate('Bruce Wayne',assertion(First == 'Bruce'),assertion(Last == 'Wayne').
:- end_tests(separate).
运行测试用例看起来不错:
?- run_tests(separate).
% PL-Unit: separate . done
% test passed
true.
现在我们只需要在名称列表上应用 separate/3
。我们可以使用 maplist/3
,但让我们使用递归定义:
% separate_all(+ListOfNames,-ListOfFirsts,.ListOfLasts)
separate_all([],[],[]).
separate_all([Name|Ns],[First|Fs],[Last|Ls]) :-
separate(Name,separate_all(Ns,Fs,Ls).
还有一个测试用例:
:- begin_tests(separate_all).
test(all_1) :-
separate_all(['Peter Parker','Bruce Wayne'],FirstNames,LastNames),assertion(FirstNames == ['Peter','Bruce']),assertion(LastNames == ['Parker','Wayne']).
:- end_tests(separate_all).
所以:
?- run_tests(separate_all).
% PL-Unit: separate_all . done
% test passed
true.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。