首页 > 解决方案 > 序言 | findall 与另一个 findall 的结果列表

问题描述

如何通过特定条件获取值,然后使用这些选定元素从其他事实系列中获取值?

我有这个代码

%code, date, amount
values1('AAA', date(02, 03, 2020), 1000).
values1('AAA', date(31, 03, 2020), 2000).
values1('BBB', date(02, 04, 2020), 1350).
values1('BBB', date(15, 04, 2020), 1500).
values1('CCC', date(23, 05, 2020), 5500).
values1('CCC', date(01, 05, 2020), 750).
values1('DDD', date(06, 05, 2020), 3560).
values1('AAA', date(18, 06, 2020), 4600).
values1('CCC', date(27, 07, 2020), 1200).

%code, percent
values2('AAA', '0.2').
values2('BBB', '0.25').
values2('CCC', '0.55').
values2('DDD', '0.98').

predicate1(Code, Percent) :- 
    findall(Code, (values1(Code, _, Value), Value > 1000), Code),
    findall(Percent, values2(Code, Percent), Percent).

For example in this case the idea it's get Code which amount is bigger than 1000, and when there are selected get the percent from value2, but the Percent list it's return empty. 为什么会这样?

这是回报

predicate1(Code, Percent).
Code = ['AAA', 'BBB', 'BBB', 'CCC', 'DDD', 'AAA', 'CCC'],
Percent = []

可能是代码列表中的元素数量和值2的事实数量之间的差异?

标签: prolog

解决方案


你有一个错字和(几个)逻辑错误。

的值Code进入 :Code列表CodeListCode您在第一和第三位置有变量。用这个:

findall(Code, (values1(Code, _, Value), Value > 1000), CodeList).

运行:

?- findall(Code, (values1(Code, _, Value), Value > 1000), CodeList).
CodeList = ['AAA', 'BBB', 'BBB', 'CCC', 'DDD', 'AAA', 'CCC'].

通过使用谓词来删除重复元素setof/3

但是,setof/3要求您指示(用插入符号“存在量化”:)Value^Date^在内部目标之外不可见的变量,否则回溯 和 的可能值ValueDate发生在之外setof/3

?- setof(Code, Value^Date^(values1(Code, Date, Value), Value > 1000), CodeList).
CodeList = ['AAA', 'BBB', 'CCC', 'DDD'].

现在你只需要“加入”任何带有“百分比”的“代码”......在setof/3

?- setof([Code,Percent], 
         Value^Date^(values1(Code, Date, Value),
                     Value > 1000,
                     values2(Code,Percent)),
         Set).

Set = [['AAA', '0.2'], ['BBB', '0.25'], ['CCC', '0.55'], ['DDD', '0.98']].

您可以将其打包到一个谓词中,该谓词回溯setof/3结果:

gimme(Code, Percent) :-
   setof([Code,Percent], 
            Value^Date^(values1(Code, Date, Value),
                        Value > 1000,
                        values2(Code,Percent)),
            Set),
   member([Code,Percent],Set).

请注意,在s的调用中CodePercent内部的变量的重用实际上是可以的:这些不是相同的变量。setof/3member/2

所以:

?- gimme(Code,Percent).
Code = 'AAA',
Percent = '0.2' ;
Code = 'BBB',
Percent = '0.25' ;
Code = 'CCC',
Percent = '0.55' ;
Code = 'DDD',
Percent = '0.98'.

推荐阅读