最简单的解决方案是将其转换为列表,使用谓词过滤列表,然后构造一个新的关联。
:- use_module(library(assoc)).
:- use_module(library(apply)).
filter_assoc_l(Filter, In, Out) :-
assoc_to_list(In, List),
include(Filter, List, OutList),
list_to_assoc(OutList, Out).
你显然不能这样做。但是您仍然需要一种方法来迭代 assoc 的所有项目,而无需进入失败驱动的循环,该循环将在每次失败后撤消您的绑定。gen_assoc
将为您提供所有密钥,但您要么必须使用findall/3
(使其与将其转换为列表相同),要么在每次绑定后都必须失败(撤消您的工作)。
这里的另一种方法是仅获取键列表,然后在值与过滤器不匹配时使用删除谓词删除它们。首先,我们需要获取键,然后调用辅助谓词来遍历键列表:
filter_assoc_unlist(Filter, In, Out) :-
assoc_to_keys(In, Keys),
filter_assoc_keys(Filter, In, Keys, Out).
现在我们可以检索当前的键/值(键列表的头部),然后调用您的过滤谓词来检查它。如果它通过了,我们只是重复;如果失败,我们将其删除并将删除的结果传递给递归步骤。
filter_assoc_keys(Filter, In, [Key|Keys], Out) :-
min_assoc(In, Key, Value),
(call(Filter, Key-Value) ->
filter_assoc_keys(Filter, In, Keys, Out)
;
del_assoc(Key, In, _, Next),
filter_assoc_keys(Filter, Next, Keys, Out)
).
当我们用完键时,输入就是输出:
filter_assoc_keys(_, Out, [], Out).
我不知道这是否符合您的标准,但我希望它符合。