1

所以我试图通过直接在 split 中使用排序库谓词来摆脱包装子句。split 所做的只是从如下所示的列表中生成一个数字列表: [1:2,3:2,4:6] ---split--> [1,2,3,2,4,6 ]。但是生成的列表包含重复项,我不希望这样,所以我使用包装器来组合拆分和排序,然后生成所需的结果:[1,2,3,4,6]。

我真的很想摆脱包装器,只在拆分中使用排序,但是我不断收到“错误:排序/2:参数没有充分实例化。” 有任何想法吗?谢谢 :)

split([],[]).
split([H1:H2|T],[H1,H2|NT]) :-
    split(T,NT).

wrapper(L,Processed) :- 
    split(L,L2),
    sort(L2,Processed).
4

1 回答 1

1

我真的很想摆脱包装器,只在 split 中使用 sort

然后使用findall复杂的目标,例如

split(Edges, NodeSet) :-
    findall(Node,
            (member(Edge, Edges), (Edge = (Node:_); Edge = (_:Node))),
            NodeList),
    sort(NodeList, NodeSet).

然而,一旦你开始使用聚合谓词,你也可以跳过sortand 使用setof

split(Edges, NodeSet) :-
    setof(Node, Edge^Pair^(member(Edge, Edges),
                           Edge =.. [:|Pair],
                           member(Node,Pair)),
          NodeSet).

读作:获取所有Nodest 存在Edge和存在Pairst (等)的集合并调用它NodeSet

( =.."univ") 运算符解构一对:Edge =.. [:, Left, Right]。为了更好的可读性,您可以编写一个单独的谓词来从边缘获取节点:

% endpoint(Edge, Node) is true iff Node is an endpoint of Edge
endpoint(Node:_, Node).
endpoint(_:Node, Node).

split(Edges, NodeSet) :-
    setof(Node, Edge^(member(Edge, Edges), endpoint(Edge, Node)), NodeSet).

编辑在您尝试这种方法之前,请参阅此答案下方的讨论,了解这是否比 OP 的原始代码更好。

于 2012-11-15T17:03:41.483 回答