setof创建了许多列表而不是一个列表序言

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了setof创建了许多列表而不是一个列表序言相关的知识,希望对你有一定的参考价值。

我有一个我使用prolog创建的函数,由于某种原因它总是为每个元素而不是一个列表创建多个列表,有人可以帮助我吗?

这是我写的:(问题是最后一个函数创建了很多列表)

father(_father,_child) :- parent(_father,_child), gender(_father,male).
mother(_mother,_child) :- parent(_mother,_child), gender(_mother,female).

couple(_woman,_man):- gender(_woman,female),gender(_man,male),parent(_man,_child),parent(_woman,_child).

parents(_woman,_man,_child) :- father(_man,_child),mother(_woman,_child).
count([],0).
count([H|T],N) :- count(T,N1) , N is N1+1.

child_to_couple(_woman,_man,_num):- couple(_woman,_man),findall(_child,parents(_woman,_man,_child),_childs),count(_childs,_num).

num_of_childs(_list):- couple(_woman,_man),setof(childrens(_man,_woman,_num),child_to_couple(_woman,_man,_num),_list).

数据示例:

gender(sagi,male).
gender(limor,female).
gender(yuval,male).
gender(gilad,male).
gender(shahaf,male).
gender(yaara,female).
parent(eyal,noam).
parent(shiri,yuval2).
parent(eyal,yuval2).
parent(shiri,yonatan).
parent(eyal,yonatan).
parent(shahaf,gan).
parent(yaara,gan).

但是当我跑

 ?- num_of_childs(_x).

我明白了:

_x = [childrens(mordechai, miriam, 1)] ;
_x = [childrens(salax, naima, 1)] ;
_x = [childrens(eli, bella, 2)] ;
_x = [childrens(eli, bella, 2)] ;
_x = [childrens(zvi, tova, 1)] ;
_x = [childrens(avram, yokeved, 1)] ;
_x = [childrens(haim, irit, 3)] ;
_x = [childrens(haim, irit, 3)] ;
_x = [childrens(haim, irit, 3)] ;
_x = [childrens(guy, pelit, 2)] ;
_x = [childrens(guy, pelit, 2)] ;
_x = [childrens(eyal, shiri, 3)] ;
_x = [childrens(eyal, shiri, 3)] ;
_x = [childrens(eyal, shiri, 3)] ;
_x = [childrens(sagi, limor, 2)] ;
_x = [childrens(sagi, limor, 2)] ;
_x = [childrens(shahaf, yaara, 1)] ;

代替:

_x = [childrens(sagi, limor, 2),childrens(sagi, limor, 2),childrens(shahaf, yaara, 1),..........etc]
答案

你的num_of_childs/1couple/2之前调用setof/3,所以你得到couple/2返回的结果数。由于child_to_couple/3也称couple/2你实际上根本不需要它。

num_of_childs(L) :- findall(childrens(M,W,N),child_to_couple(W,M,N),L).

但最大的问题是couple/2,你写的方式,每个孩子总是成功一次。这会传播,以便child_to_couple/2num_of_childs/1也能多次成功。

如果你改变这个

couple(W,M):-
 gender(W,female), gender(M,male),
 ( parent(M,C), parent(W,C) -> true ; false ).

无论孩子的数量如何,每对夫妇只能得到一个结果。我觉得可能有更简单的方法来实现这一目标,但我无法找到它。

?- num_of_childs(L).
L = [childrens(eyal,shiri,2),childrens(shahaf,yaara,1)] ? ;
no

增加:使用切割会稍微简单但也更丑陋。

以上是关于setof创建了许多列表而不是一个列表序言的主要内容,如果未能解决你的问题,请参考以下文章

架构丰富的代码片段也应该用于产品列表吗?

根据字符串名称而不是列表视图项位置替换片段并启动活动

android如何使用listview而不是scrollview

片段中的Android ListView

如何将 r ggplot 图存储为 html 代码片段

仅在序言中平整列表的一个级别