【问题标题】:Working with list of lists in Prolog在 Prolog 中使用列表列表
【发布时间】:2012-01-25 00:21:49
【问题描述】:

请帮我解决这个问题: 我有一个列表列表

[[1,2],[3,4]]

如何获得:

[1,3]

[1,4]

[2,3]

[2,4]

或者如果我有一个列表列表

[[1,2],[3,4],[6,7]]

如何获得:

[1,3,6]

[1,3,7]

[1,4,6]

[1,4,7]

[2,3,6]

[2,3,7]

[2,4,6]

[2,4,7]

【问题讨论】:

标签: list prolog cartesian-product cross-product


【解决方案1】:

访问单个列表元素的谓词是最基本的 Prolog 构建块:member/2

你想要一个所有列表元素的列表:maplist/3 进行这样的映射。这样我们就可以写

combine(Ls, Rs) :-
    maplist(get1, Ls, Rs).
get1(L, E) :-
    member(E, L).

请注意,get1/2 仅是必需的,以便我们交换 member/2 参数。但是因为在(纯)Prolog 中我们描述的是参数之间的关系,所以我们可以交换参数的顺序并进一步简化它:

combine(Ls, Rs) :-
    maplist(member, Rs, Ls).

测试输出:

?- combine( [[1,2],[a,b]], Xs).
Xs = [1, a] ;
Xs = [1, b] ;
Xs = [2, a] ;
Xs = [2, b].

%% this is the same as:
       %% maplist( member, Xs, [[1,2],[a,b]]) :-
       %%          member( X1,  [1,2]      ),
       %%          member( X2,        [a,b]),  Xs = [X1,X2].

编辑

开个玩笑:真的,我的第一个 combine/2 应该这样写

combine(Ls, Rs) :-
    maplist(rebmem, Ls, Rs).
rebmem(L, E) :-
    member(E, L).

【讨论】:

  • 很好地使用了会员和地图列表!非常令人印象深刻!
  • 为什么使用这个命令:findall(X, maplist(member, [[a,b,c], [1,2,3]], X), L)。输出无限?
  • @mso: member/2 有一个列表作为第二个参数。否则它会在回溯时“建立”它,因此它不会在由 findall 驱动时终止
  • 一个小宝石,这东西。 :)
【解决方案2】:

你可以这样做:

lists([], []).
lists([[Head|_]|Lists], [Head|L]):-
  lists(Lists, L).
lists([[_,Head|Tail]|Lists], L):-
  lists([[Head|Tail]|Lists], L).

也就是说,取输入列表中第一个列表的第一个元素,然后递归地继续处理剩余的列表。作为第二次机会,跳过该元素并使用剩余的元素重做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-19
    • 1970-01-01
    相关资源
    最近更新 更多