2015-09-27 40 views
1

我有这样的Prolog的一个表:聚集总和的Prolog

invoice(number, locality, value) 

invoice(1, madrid, 100) 
invoice(2, lisbon, 200) 
invoice(3, london, 300) 
invoice(4, madrid, 300) 
invoice(5, lisbon, 200) 
invoice(6, paris, 100) 

我怎样才能得到所在地agreggate总和?

答案应该是像在Excel做数据透视表..

里斯本总数:400 马德里总数:400 巴黎总数:100 伦敦总:300

回答

2

只是为了避免稀客认为冗长的代码是必要来完成这些基本的东西,这里是库(aggregate)的方式:

?- aggregate(sum(Value), Number^invoice(Number,Locality,Value), Sum). 
Locality = lisbon, 
Sum = 400 ; 
Locality = london, 
Sum = 300 
... 

也就是说,我们可以选择'pivot'列。要获得完整的结果,换到另一个汇总:

?- aggregate(set(Locality=Sum), aggregate(sum(Value), Number^invoice(Number,Locality,Value), Sum), All). 
All = [lisbon=400, london=300, madrid=400, paris=100]. 
1

有多种方法。 以下程序是其中之一。

/* agreggate_sum. */ 

agreggate_sum :- 
     sum_calc(Data_list), 

     write('locality, total'), nl, 

     write_data(Data_list). 


sum_calc(Data_list) :- 
     findall((Locality, Value), invoice(_, Locality, Value), Invoice_list), 
     data_reduction(Invoice_list, [], Data_list). 


data_reduction([], Data_list, Data_list) :- !. 

data_reduction([(Locality, Value) | Result], Tmp_list, Data_list) :- 
     data_reduction2(Tmp_list, Locality, Value, Tmp_list2 ), 
     data_reduction(Result, Tmp_list2, Data_list). 


data_reduction2([], Locality, Value, [(Locality, Value)]) :- !. 

data_reduction2([(Locality, Total_Value) | Result], Locality, Value, [(Locality, Total_Value2) | Result]) :- 
     !, 
     Total_Value2 is Total_Value + Value. 

data_reduction2([(Locality2, Total_Value) | Result], Locality, Value, [(Locality2, Total_Value) | Result2]) :- 
     data_reduction2(Result, Locality, Value, Result2). 


write_data([]) :- !. 

write_data([(Locality, Total_Value) | Result]) :- 
     write(Locality), write(', '), write(Total_Value), nl, 
     write_data(Result). 


invoice(1, madrid, 100). 
invoice(2, lisbon, 200). 
invoice(3, london, 300). 
invoice(4, madrid, 300). 
invoice(5, lisbon, 200). 
invoice(6, paris, 100). 

结果

9 ?- agreggate_sum. 

locality, total 

madrid, 400 

lisbon, 400 

london, 300 

paris, 100 
+0

过多削减!实际上,OP可以得到他们需要的印象,而不是...... – CapelliC

3

另一种解决方案是让镇 - 值对,它们分组由镇,并计算出资金用于城镇:

aggregate_sum_by_town(Result) :- 
    findall(T-V, invoice(_, T, V), TVs), 
    keysort(TVs, Ps), 
    group_pairs_by_key(Ps, G), 
    pairs_keys_values(G, Ks, Vs), 
    maplist(sumlist, Vs, Ss), 
    pairs_keys_values(Result, Ks, Ss). 

?- aggregate_sum_by_town(Result). 
Result = [lisbon-400, london-300, madrid-400, paris-100].