How apply findall to find several fields | Prolog

Viewed 67

I'm trying to get 2 values from a knowledge base

%code, date, amount
values1('AAA', date(02, 03, 2020), 1000).
values1('AAA', date(31, 03, 2020), 2000).
values1('AAA', date(02, 04, 2020), 1350).
values1('BBB', date(15, 04, 2020), 1500).
values1('CCC', date(15, 05, 2020), 950).

I want to get the Code and Value by Month in two list. My idea was use findall two times, first to get the Code, and next to get Value, but it's not return the values, just Code.

function4(Month, Value, Code) :- 
    findall(Code, values1(Code, date(_, Month, _), _), Code),
    findall(Value, values1(Code, _, Value), Value).

I'm newbie on prolog and any advice wuold be greatly appreciated.

1 Answers

You are not using findall/3 correctly. For a list of all Codes, Values in a particular month separately:

get_months_data1(Month, Codes, Values) :-
    findall(Code, values1(Code, date(_, Month, _), _), Codes),
    findall(Value, values1(_, date(_, Month, _), Value), Values).
?- get_months_data1(03, C, V).
C = ['AAA', 'AAA'],
V = [1000, 2000].

?- get_months_data1(04, C, V).
C = ['AAA', 'BBB'],
V = [1350, 1500].

?- get_months_data1(05, C, V).
C = ['CCC'],
V = [950].

If you do not want duplicate entries like ['AAA', 'AAA'] above, you can also use setof/3. If you want them Code, Value together you can have:

get_months_data(Month, Data) :-
    findall(tr(Code, Value), values1(Code, date(_, Month, _), Value), Data).

This gives

?- get_months_data(03, D).
D = [tr('AAA', 1000),  tr('AAA', 2000)].

?- get_months_data(04, D).
D = [tr('AAA', 1350),  tr('BBB', 1500)].

?- get_months_data(05, D).
D = [tr('CCC', 950)].

Related