从多个列表中删除项目

时间:2016-02-08 18:37:15

标签: list prolog meta-predicate

我有一个子问题,其解决方案比我认为必要的解决方案更大。

问题定义如下

从组中ID为Y和Z或A和B之间的所有组中删除X

表示为伪查询,它看起来像Y,Z,A,B设置为0,1,3,4

remove(X, 
       [ period(0,1), period(3,4) ],
       [ 
          group(0, [ subgroup([_,_,X,_,_]), subgroup([X])]),
          group(1, [ subgroup([X])]),
          group(2, [ subgroup([_,_,X])]),
          group(3, [ subgroup([_,X,_])]),
          group(4, [ subgroup([X,_,_])])
       ], UpdatedGroups).

结果将是

UpdatedGroups = [ 
    group(0, [ subgroup([_,_,_,_]), subgroup([])]),
    group(1, [ subgroup([])]),
    group(2, [ subgroup([_,_,X])]),
    group(3, [ subgroup([_,_])]),
    group(4, [ subgroup([_,_])])
]

所以,我的解决方案是:

当前期间的开始时间小于或等于当前期间的结束时,请在组中删除X,同时"递增"一天的开始。重复直到不再有句号

在组中删除X是通过"循环"所有组并检查它是否与句点匹配,如果它确实从子组中删除了用户,这又是通过"循环"来完成的。

这是一个非常乏味但直接的解决方案,现在我的问题是我经常发现自己正在做这样的事情,并且找不到以不那么全面的方式做到这一点的方法。

除了我的还有其他方法还没有覆盖50多行吗?

更新

非常感谢,代码变得如此清晰 - 它可能会更进一步,但现在可以实际发布在这里(这有点修改 - 但逻辑就在那里)

inPeriods(Day, [ period(Start,End) | _ ]) :- between(Start,End, Day).
inPeriods(Day, [ _ | RemainingPeriods ]) :- inPeriods(Day, RemainingPeriods).

ruleGroupsInPeriod(Periods, rulegroup(Day,_)) :- inPeriods(Day, Periods).

removeUserFromRelevantRuleGroups(UserId, Periods, RuleGroups, UpdatedRuleGroups) :-
    include(ruleGroupsInPeriod(Periods), RuleGroups, IncludedRuleGroups).
    exclude(ruleGroupsInPeriod(Periods), RuleGroups, ExcludedRuleGroups),
    maplist(updateRuleGroup(UserId), IncludedRuleGroups, UpdatedIncludedRuleGroups)
    append(UpdatedIncludedRuleGroups, ExcludedRuleGroups, UpdatedRuleGroups).

updateRuleGroup(UserId, rulegroup(X, RuleList), rulegroup(X, UpdatedRuleList)) :-
    maplist(updateRule(UserId), RuleList, UpdatedRuleList).

updateRule(UserId, rule(X, UserList), rule(X, UpdatedUserList)) :-
    delete(UserList, UserId, UpdatedUserList).

1 个答案:

答案 0 :(得分:2)

您描述的模式非常常见,所有严肃的Prolog系统都附带强大的元谓词(即,其参数表示谓词的谓词),可以让您轻松地描述这个以及许多其他常见情况。灵活的方式,最多使用一些简单的附加定义来为您的具体关系。

Richard O'Keefe对An elementary Prolog Library的提议包含许多此类谓词的描述和实现,这些谓词在所有主要的Prolog实现和Prologue for Prolog中都越来越多。

特别是,你应该学习:

  • include/3
  • exclude/3
  • maplist/[2,3]

请注意,虽然许多描述的谓词都是不纯,因为它们会破坏代码的声明性属性。与真实关系相反,在保持逻辑健全性的同时,您将无法在所有方向上使用它们。

练习:上面提到的三个谓词中的哪一个(如果有的话)在其他一切都是纯粹的时候会保留,哪些(如果有的话)不存在?