List Prolog-更改列表的元素

List Prolog-更改列表的元素,list,prolog,List,Prolog,完成一本书中的初学者练习,我想取一个列表X并更改其元素,以便对于一些[H | X]新列表Y将头元素设置为(H-1,H+1) 比如: X=[1,20,300] --> Y=[(0,2),(19,21),(299,301)] 到目前为止,我添加的是第一个元素,但随后返回一些奇怪的“\u编号”。到目前为止,我所拥有的: switch([], []). switch([H|X], Y) :- H1 is H-1, H2 is H+1, append([(H1,H2)], [],

完成一本书中的初学者练习,我想取一个列表
X
并更改其元素,以便对于一些
[H | X]
新列表
Y
元素设置为
(H-1,H+1)

比如:

X=[1,20,300] --> Y=[(0,2),(19,21),(299,301)]
到目前为止,我添加的是第一个元素,但随后返回一些奇怪的“\u编号”。到目前为止,我所拥有的:

switch([], []).
switch([H|X], Y) :-
   H1 is H-1,
   H2 is H+1,
   append([(H1,H2)], [], Y).

这里有两个问题:

  • append
    ing
    [(H1,H2)]
    []
    为我们提供了一个我们可以提前知道的结果:
    Y
    也将是
    [(H1,H2)]
  • 在本例中,您不会对尾部
    X
    执行任何操作,因此只处理第一个元素,然后丢弃该元素
  • 因此,谓词将只处理第一个元素,并使用该元组创建一个列表,如:

    ?- switch([1,2,3], Y).
    Y = [(0, 2)].
    
    事实上,这里根本不需要
    append/3
    :我们有两个参数,如果前者是非空的,那么后者也是非空的,反之亦然。因此,我们的递归子句具有以下形状:

    switch([], []).
    switch([H|T], [(H1, H2)|TT]) :-
        %% ...
    因此,我们需要指定
    H
    H1
    H2
    之间的关系;和
    T
    TT
    (“元组列表”的其余元素)。至于
    H
    ,这已经实现了
    H1是H-1
    H2是
    H+1
    。对于
    T
    TT
    ,我们只需要继续处理,所以我们使用
    T
    TT`进行递归调用:

    switch([], []).
    switch([H|T], [(H1, H2)|TT]) :-
        H1 is H-1,
        H2 is H+1,
        switch(T, TT).
    使用 在这里,我们只能在一个方向上进行查询:如果我们用第二个参数统一一个2元组列表,那么Prolog就不能派生第一个列表中的元素。但是,我们可以定义这些元素之间的约束,因此,我们可以从几个方向进行查询:

    :- use_module(library(clpfd)).
    
    switch([], []).
    switch([H|T], [(H1, H2)|TT]) :-
        H1 #= H-1,
        H2 #= H+1,
        switch(T, TT).
    合作 我们正在解决的任务是典型的“映射任务”。因此,我们可以“废弃我们的样板”,并使用:

    :-使用_模块(库(clpfd))。
    开关组(H,(H1,H2)):-
    H1#=H-1,
    H2#=H+1。
    开关(L1、L2):-
    
    地图列表(切换元组,L1,L2)。
    非常感谢您给出了这个详细的答案。我一直在与列表操作作斗争,你的解释似乎很好!
    ?- switch(L, [(1, A), (3, 5), (C, 7)]).
    L = [2, 4, 6],
    A = 3,
    C = 5.
    
    :- use_module(library(clpfd)).
    
    switch_tuple(H, (H1, H2)) :-
        H1 #= H-1,
        H2 #= H+1.
    
    switch(L1, L2) :-
        maplist(switch_tuple, L1, L2).