简体   繁体   English

Prolog - 替换列表元素

[英]Prolog - replacing list elements

So I have a program that has a predicate to replace the first occurrence of some element of a list with a given new element and produce a new list. 所以我有一个程序,它有一个谓词用一个给定的新元素替换列表中某个元素的第一个出现并生成一个新列表。 I have it done like so: 我这样做了:

    changeFst(OldE,[OldE|T],NewE,[NewE|T]):-!.
    changeFst(OldE,[_|T],NewE,_):- changeFst(OldE,T,NewE,_),!.

For example if you give (2,[1,2,3,4,2],10,X) it should give you back X=[1,10,3,4,2] 例如,如果你给(2,[1,2,3,4,2],10,X)它应该给你回X = [1,10,3,4,2]

now im making the part that changes the last occurrence (in the example it would return X=[1,2,3,4,10]). 现在我正在制作改变最后一次出现的部分(在例子中它将返回X = [1,2,3,4,10])。 Here's my code: 这是我的代码:

    changeLast(OldE,OldL,NewE,NewL):-
       reverse(OldE,X), 
       changeFst(OldE,X,NewE,NewL),
       !.

so this works in fact perfectly but the thing is it returns me the list reversed ( in my upper example it returns me [10,4,3,2,1] instead of [1,2,3,4,10] ) 所以这实际上是完美的,但事情是它返回我反转的列表(在我的上例中它返回我[10,4,3,2,1]而不是[1,2,3,4,10]

How can I just reverse this again to get my answer properly displayed? 我怎样才能再次将其反转以正确显示我的答案?

Your definition of changeFst/4 is incorrect on many counts like changeFst(o,[o,o],n,[m,y,s,t,e,r,y]). 你对changeFst/4定义在许多方面是不正确的,例如changeFst(o,[o,o],n,[m,y,s,t,e,r,y]). succeeds, but clearly it should fail. 成功,但显然它应该失败。 The reason is your incorrect usage of cuts. 原因是你不正确使用削减。 If you want to learn Prolog, stick to the pure declarative subset first. 如果你想学习Prolog,首先要坚持纯粹的声明性子集。 That means no cuts, and no side-effects. 这意味着没有削减,也没有副作用。

So here is a definition that does not rely on cuts: 所以这里的定义不依赖于削减:

changeFst(Old,[Old|Olds],New,[New|Olds]).
changeFst(Old,[E|Olds],New,[E|News]):-
   dif(Old, E),
   changeFst(Old,Olds,New,News).

One advantage of such a pure relation is that we can use the most general query to see what answers we get: 这种纯关系的一个优点是我们可以使用最通用的查询来查看我们得到的答案:

| ?- changeFst(Old, Olds, New, News).
Olds = [Old|_A],
News = [New|_A] ? ;
Olds = [_A,Old|_B],
News = [_A,New|_B],
prolog:dif(Old,_A) ? ;
Olds = [_A,_B,Old|_C],
News = [_A,_B,New|_C],
prolog:dif(Old,_A),
prolog:dif(Old,_B) ? ;
Olds = [_A,_B,_C,Old|_D],
News = [_A,_B,_C,New|_D],
prolog:dif(Old,_A),
prolog:dif(Old,_B),
prolog:dif(Old,_C) ? ...

Do you note that the answers always contain for Olds a partial list ? 你是否注意到答案总是包含Olds部分列表 Like: Olds = [Old|_A] in the first answer. 喜欢: Olds = [Old|_A]在第一个答案中。 That might be a bit too general, after all it means that even nonlists are now accepted: 这可能有点过于笼统,毕竟这意味着即使是非名单也会被接受:

| ?- changeFst(o,[o|nonlist], New, News).
News = [New|nonlist] ? 
yes

So you might want to ensure that Olds and News are always lists. 因此,您可能希望确保OldsNews始终是列表。

But my point to show this is rather to you show you that with a pure relation you see many things that a cut-ridden program can never show you that directly. 但是,我要向你展示这一点,而是告诉你,只要有一种纯粹的关系,你就会看到许多东西,这些东西是一个切割不前的程序永远无法直接向你展示的东西。

If we are at it: What to do with the empty list? 如果我们在这:它如何处理空列表? The current version suggests that changeFst/4 should fail. 当前版本表明changeFst/4应该失败。 Not sure what you want here, but in case you want it to succeed, add a fact changeFst(_,[],_,[]). 不知道你想要什么,但如果你想要它成功,添加一个事实changeFst(_,[],_,[]). first. 第一。

See this answer for a definition of dif/2 ( ) should your Prolog not support it. 如果您的Prolog不支持,请参阅此答案以获取dif/2 )的定义。

Stay pure and efficient, by using if_/3 together with (=)/3 as proposed by @false: 保持纯粹和高效,使用if_/3和@false建议的(=)/3

changeFst(Old,Olds,New,News) :-
   list_change_first_(Olds,News,Old,New).

list_change_first_([],[],_,_).
list_change_first_([X|Xs],[Y|Ys],Old,New) :-
   if_(X = Old, (Y = New, Ys = Xs),
                (Y = X,   list_change_first_(Xs,Ys,Old,New))).

Sample queries: 示例查询:

?- changeFst(2,[1,2,3,4,2],10,Xs).
Xs = [1,10,3,4,2].                         % succeeds deterministically

?- changeFst(o,[o,o],n,[m,y,s,t,e,r,y]).
false.                                     % expected result

?- changeFst(Old,Olds,New,News).
Olds = [],             News = []                                       ;
Olds = [Old|_A],       News = [New|_A]                                 ;
Olds = [_A],           News = [_A],           dif(_A,Old)              ;
Olds = [_A,Old|_B],    News = [_A,New|_B],    dif(_A,Old)              ;
Olds = [_A,_B],        News = [_A,_B],        dif(_A,Old), dif(_B,Old) ;
Olds = [_A,_B,Old|_C], News = [_A,_B,New|_C], dif(_A,Old), dif(_B,Old) % and so on...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM