在prolog中重新组织一个列表

时间:2014-12-04 10:53:43

标签: list prolog

我正在尝试编写一些Prolog代码来获取如下列表:

[[park, joe], [park, bob], [park, kate], [school, joe], [zoo, amy], [zoo, ted]]. 

并将列表组织成表格:

[[park,[joe, bob, kate]], [school,[joe]], [zoo,[amy, ted]]]. 

可以假设每个元素的所有匹配头(park = park,zoo = zoo)在列表中直接相邻,因为我创建列表的代码按字母顺序对其进行排序。我似乎无法弄清楚如何实现这一点并且似乎每次都会出现错误:(。下面是我在上一个状态中运行的代码,它运行时没有错误,我将尝试解释我是什么思。

merge([],[]).
merge([First|Rest], Z) :- 
merge(Rest, U),
[Meet1, Person1] = First,
( =(U, []) ->   % beginning case from recursion, U is empty
    Meet2 = [],
    Person2 = [];
    [[Meet2|Person2]|_] = U),
 ( =(Meet1, Meet2) -> % Case of matching heads, combine the tails
    print('Match '),
    append([First], U, Z); 
 print('No-match '), % otherwise, not matching
append([First], U, Z) ).

所以我试图做的是使用appends将所有更改添加到U并使用Z将其返回到控制台,例如,

( =(Meet1, Meet2) ->
  append(Person1, Person2, Combpersons),
  append([Meet1], [Combpersons], T),
  append(T, U, Z);
   ...no match code here..).

然而,当我尝试在我放在这里的第一个代码块中更改或添加这样的附加内容时,我的代码会过早地以错误结束。即使改变诸如将附加([First],U,Z)转换为追加([Meet1],U,Z)也会使我的代码以错误结束,我不明白为什么。任何有关创建解决方案的帮助/提示都将受到赞赏。

3 个答案:

答案 0 :(得分:1)

如果您将初始列表作为对列表,则可以使用SWI-Prolog中提供的library(pairs)

?- group_pairs_by_key([park-joe, park-bob, park-kate, school-joe, zoo-amy, zoo-ted], G).
G = [park-[joe, bob, kate], school-[joe], zoo-[amy, ted]].

使用该库不仅仅为您提供“重组”。还有library(ugraphs),可能更适合,取决于你正在做什么。

答案 1 :(得分:1)

我认为学习任何语言都是一个过程,其中低级别和高级别问题必须交错。到目前为止,您正在学习基本语法。但为什么你使用这种不可读的结构?当然,任何编程语言都建立在一组模式之上,通常由libraries覆盖。考虑

l2p([A,B],A-B).

?- maplist(l2p,[[park, joe], [park, bob], [park, kate], [school, joe], [zoo, amy], [zoo, ted]], L),group_pairs_by_key(L,G).
L = [park-joe, park-bob, park-kate, school-joe, zoo-amy, zoo-ted],
G = [park-[joe, bob, kate], school-[joe], zoo-[amy, ted]].

无论如何,这是你的代码重组:

merge([],[]).
merge([[Meet, Person]|Rest], Z) :- 
    merge(Rest, U),
    (   U = []
    ->  % beginning case from recursion, U is empty
        Z = [[Meet, [Person]]]
    ;   U = [[Meet, Persons] | Rest1]
    ->  % Case of matching heads, combine the tails
        Z = [[Meet, [Person | Persons]] | Rest1]
    ;   % otherwise, not matching
        Z = [[Meet, [Person]] | U]
    ).

答案 2 :(得分:0)

您的代码失败,因为您在检查是否有任何内容之前尝试提取该位置和该人。

此处append没有用,重新排序看起来相当复杂,但我使用变量名称做到了最好。此外,您只需要一个->:如果您没有找到具有相同第一个坐标的元组,那么您想要创建一个新的元组,这并不重要如果之前没有。

merge([],[]).
merge([[Place,Person]|Rest], [[Place,Group]|OtherGroups]) :- 
    merge(Rest, U),
    (U = [[Place,Others]|OtherGroups] ->
     Group = [Person|Others];
     [OtherGroups,Group] = [U, [Person]]).

编辑:我因可读性原因改变了解决方案。