在prolog中替换空格

在prolog中替换空格,prolog,swi-prolog,iso-prolog,Prolog,Swi Prolog,Iso Prolog,在prolog中,是否可以用给定的字符替换字符串的所有空格? 范例- 如果我有一个变量你今天好吗?我想你今天好吗?用于原子 有很多方法可以做到这一点。我发现使用以下方法特别简单: 用于SWI字符串 也可以使用SWI字符串执行上述操作。不幸的是,没有string\u list\u concat/3,这会使转换变得微不足道。非常通用,但它只完成一半的工作: ?- split_string("How are you today?", " ", "", Words). Words = ["How", "

在prolog中,是否可以用给定的字符替换字符串的所有空格? 范例- 如果我有一个变量
你今天好吗?
我想
你今天好吗?

用于原子 有很多方法可以做到这一点。我发现使用以下方法特别简单:

用于SWI字符串 也可以使用SWI字符串执行上述操作。不幸的是,没有
string\u list\u concat/3
,这会使转换变得微不足道。非常通用,但它只完成一半的工作:

?- split_string("How are you today?", " ", "", Words).
Words = ["How", "are", "you", "today?"].
我们可以自己定义
string\u list\u concat/3
(定义这一点的第一次尝试如下所示),或者我们需要稍微不同的方法,例如重复

然后:

?- string_list_concat(Words, " ", "How are you today?"), string_list_concat(Words, "_", Result).
Words = ["How", "are", "you", "today?"],
Result = "How_are_you_today?".

这完全取决于你所说的字符串是什么意思。SWI为它们提供了几种版本,其中一些版本通常在任何通用Prolog中都可用,并且符合ISO标准;有些是针对SWI的,不符合要求。那么,让我们从那些普遍可用的开始:

字符串作为字符代码列表-表示代码点的整数 这种表示法通常是默认的,在SWI 7之前,它也是SWI中的默认值。最大的缺点是任意整数列表现在可能与文本混淆

:- set_prolog_flag(double_quotes, codes).

codes_replaced(Xs, Ys) :-
   maplist(space_repl, Xs, Ys).

space_repl(0' ,0'_).
space_repl(C, C) :- dif(C,0' ).

?- codes_replaced("Spaces  !", R).
R = [83, 112, 97, 99, 101, 115, 95, 95, 33] ;
false.
字符串作为字符列表-长度为1的原子 此表示法更简洁,因为它不会将整数与字符混淆,请参见如何获得更简洁的答案

:- set_prolog_flag(double_quotes, chars).

chars_replaced(Xs, Ys) :-
   maplist(space_replc, Xs, Ys).

space_replc(' ','_').
space_replc(C, C) :- dif(C,' ').

?- chars_replaced("Spaces  !", R).
R = ['S', p, a, c, e, s, '_', '_', !] ;
false.
弦作为原子 @WouterBeek已经向您展示了如何使用特定于SWI的内置设备来实现这一点。我将重复使用上面的内容:

atom_replaced(A, R) :-
   atom_chars(A, Chs),
   chars_replaced(Chs, Rs),
   atom_chars(R, Rs).

?- atom_replaced('Spaces  !',R).
R = 'Spaces__!' ;
false.
到目前为止,一切都适用于

字符串作为特定于SWI的不一致数据类型
此版本不适用于任何其他系统。我提到它是为了完整性。

SWI Prolog DCGs允许一个简单的定义,使用“向后推”或“向前看”参数:

?- phrase(rep_string(` `, `_`), `How are you`, R),atom_codes(A,R).
R = [72, 111, 119, 95, 97, 114, 101, 95, 121|...],
A = 'How_are_you'
定义是

rep_string(Sought, Replace), Replace --> Sought, rep_string(Sought, Replace).
rep_string(Sought, Replace), [C] --> [C], rep_string(Sought, Replace).
rep_string(_, _) --> [].
编辑以避免多个“解决方案”,可能是

rep_string(Sought, Replace), Replace --> Sought, !, rep_string(Sought, Replace).
rep_string(Sought, Replace), [C] --> [C], !, rep_string(Sought, Replace).
rep_string(_, _) --> [].

好的,基本上它是把字符串转换成列表,然后再转换成字符串。非常感谢它的工作。@Peter,请注意,当你使用“字符串”这个词时,实际上是指“原子”。SWI Prolog也支持字符串,但这是非标准的。我将为我的答案添加一个类似的拆分SWI字符串的解决方案。@false不能说这完全是故意的;-),但是对于这个特殊的情况,它可能是好的。您的非AR测试使情况变得更糟,因为它现在对于最一般的查询失败了。我宁愿测试一个
var/1
,然后依靠内置来完成其余的工作。@false谢谢,我已经改进了一点定义。它仍然不太存在,例如,
string\u list\u concat([],“/”,“)
失败。然而,我从来都不喜欢这样一个事实,即
原子列表([],'/,'')和
原子列表(['],'/,'')都成功了…试着键入
空格
看看会发生什么:你会得到不止一个答案。顺便说一句:反引号字符串意味着代码是特定于SWI的。
rep_string(Sought, Replace), Replace --> Sought, rep_string(Sought, Replace).
rep_string(Sought, Replace), [C] --> [C], rep_string(Sought, Replace).
rep_string(_, _) --> [].
rep_string(Sought, Replace), Replace --> Sought, !, rep_string(Sought, Replace).
rep_string(Sought, Replace), [C] --> [C], !, rep_string(Sought, Replace).
rep_string(_, _) --> [].