【问题标题】:Predicate to unzip a list解压缩列表的谓词
【发布时间】:2016-08-24 05:39:55
【问题描述】:
List1=[(x,1),(y,1),(z,1)]

我正在尝试拆分此列表:

分成两个列表:

List3=[x,y,z]
List4=[1,1,1]

所以我写了这个谓词来尝试这样做:

splt([], [], []).
splt([X|Xs], [Y|Ys], [X,Y|Zs]) :-
    splt(Xs,Ys,Zs).

但是,谓词返回的不是期望的结果:

1 ?- splt([(x,1),(y,2),(z,3)],L3,L4).
L3 = [_G1760, _G1769, _G1778],
L4 = [ (z, 1), _G1760, (y, 2), _G1769, (z, 3), _G1778].

【问题讨论】:

    标签: list prolog tuples


    【解决方案1】:

    首先,您选择的术语。这:(a, b)绝对不是您通常在 Prolog 中表示“元组”的方式。您几乎总是将a-b 用于“对”,并且在整个标准库中都使用对。

    所以您的初始列表如下所示:[x-1, y-1, z-1]

    这也应该解释您遇到问题的原因。你写了(a, b),但你的谓词写的是a, b,当你期望得到一个,(a,b)术语时,你消耗了两个元素。因此,要修复您当前的谓词,您可以编写:

    split([], [], []).
    split([X|Xs], [Y|Ys], [(X,Y)|XYs]) :-
        split(Xs, Ys, XYs).
    
    ?- split(Xs, Ys, [(x,1), (y,1), (z,1)]).
    Xs = [x, y, z],
    Ys = [1, 1, 1].
    

    但是,改为使用更传统的名称、术语顺序和 Prolog 对:

    zip([], [], []).
    zip([X-Y|XYs], [X|Xs], [Y|Ys]) :-
        zip(XYs, Xs, Ys).
    
    ?- zip([x-1, y-1, z-1], Xs, Ys).
    Xs = [x, y, z],
    Ys = [1, 1, 1].
    

    当然,SWI-Prolog 至少有一个library(pairs),它还带有一个pairs_keys_values/3

    ?- pairs_keys_values([x-1, y-1, z-1], Xs, Ys).
    Xs = [x, y, z],
    Ys = [1, 1, 1].
    

    【讨论】:

    • 很好的答案!值得扩展一下为什么 (a,b) 将是一个不好的选择来表示对:例如,原因之一是 , 已经在 Prolog 中用于许多其他事情:','/2 用于连词,@987654335 @ 在[a,b,c] 之类的列表中,甚至可以在p(A, B, C) :- ... 中分隔谓词参数。
    • (',')/2(-)/2 的缺点:它们都是关联的,而 Haskell 的 (a,b) 没有关联,你必须写 (a,(b,c))
    • @false 你的意思是(a,b,c) 最终成为','(a,','(b,c)) 而不是','(a,b,c),而a-b-c 最终成为-(-(a,b),c)
    • @Boris:是的。 Haskell 中不存在这种歧义。 (a,b,c)(a,(b,c)) 没有共同点。
    • @false 好吧,我知道这听起来很抱歉,但我一直认为a-b 是一个pair,而不是一个元组,而且我对元组的感觉是如果您在实践中将它们用作数据结构,您不妨给它们命名。什么是需要更高元组的无名元组的好例子?
    【解决方案2】:

    我觉得使用库很舒服(yall):

    ?- maplist([(X,Y),X,Y]>>true, [(x,1),(y,2),(z,3)],L3,L4).
    L3 = [x, y, z],
    L4 = [1, 2, 3].
    

    或者,也许更清楚

    ?- maplist([A,B,C]>>(A=(B,C)), [(x,1),(y,2),(z,3)],L3,L4).
    L3 = [x, y, z],
    L4 = [1, 2, 3].
    

    【讨论】:

    • 我认为第一个版本要好得多,第二个是不必要的间接。
    【解决方案3】:

    你匹配的是整个元组,而不是它的组成部分。

    您应该匹配[(X1,Y1)|XS],而不是[X|XS][Y|Ys]

    splt([],[],[]).
    splt([(X1,Y1)|Xs],[X1|T1],[Y1|T2]):-
      splt(Xs,T1,T2).
    

    这里第一项用作输入,第二项和第三项用作输出。

    Ideone 示例,使用 SWI-Prolog,here

    【讨论】:

    • 问题出在[X,Y|Zs],应该是[(X,Y)|Zs]。还是我错了?
    • @Boris 我可能是错的。但我认为第一项应该与元组匹配。而且我认为[X,Y|Zs] 是用来输出的。
    • @Boris 我在 ideone 中测试了元组匹配,选择 SWI-Prolog。
    • @Boris 更新了我的答案。老实说,当 somebody ;-) 发布了一个更好的答案时,我仍在解决这个问题。
    • 对不起 :( 但现在我更仔细地研究了这个问题:谓词定义 almost 达到了它的工作点,并且它具有带有“元组”的列表作为最后一个参数。然后,在示例中,带有元组的列表是第一个参数....
    猜你喜欢
    • 2017-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多