Prolog生成列表二元无序组合 如何去除逆序重复对
问题根因
你的修改方案失效是因为findall/3的执行逻辑:它会先完成所有符合条件的配对收集,最后才将结果集绑定到Res变量。你在收集配对的判断条件中调用\+ member([B,A], Res)时,Res还处于未实例化的状态,该判断完全不生效,自然达不到去重的效果。
最优实现方案
不需要额外做后处理去重,直接在生成配对阶段加顺序约束即可,用Prolog标准项比较符@<限制两个元素的顺序,天然避免逆序重复:
fun(List, Res):- findall( [A, B], ( member(A, List), member(B, List), A @< B ), Res ).
@<会按照Prolog的标准术语顺序比较两个项,仅当A的顺序严格早于B时返回真,本身已经隐含了A \= B的逻辑,不需要额外添加不等判断。以输入[a,b,c,d]为例,输出结果为[[a,b],[a,c],[a,d],[b,c],[b,d],[c,d]],完全符合你的需求。
备选方案(先全量生成再去重)
如果你有特殊需求必须先生成所有有序对,再做去重处理,可以用以下写法:
fun(List, Res):- findall( [A, B], ( member(A, List), member(B, List), A \= B ), AllPairs ), findall(Pair, (member(Pair, AllPairs), Pair = [A,B], \+ (member([B,A], AllPairs), [B,A] @< Pair)), Res).
该方案会保留每一组逆序对中顺序靠前的那一个,删除另一个。
内容的提问来源于stack exchange,提问作者Alessandro Muscatello
相关产品推荐
相关产品推荐

