2016-02-08 3 views
1

У меня есть подзадача, для которой решение намного больше, чем я предполагаю.Удалить элемент из нескольких списков

Проблема определяется следующим образом

Удалить X из всех групп, где группа имеет идентификатор между Y и Z или А и В

выражается в виде псевдо запроса он выглядит как это с 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

Отлично! 'nowOneMoreThingThatIsMissingIs'' using_more_readable_names'! 'unReadableNamesLikeInJava' в порядке для * переменных *, но соглашение Prolog для * predicate * names' is_to_use_underscores_between_words'. – mat

+1

Также избегайте использования * императивов *, например, «обновление» и «удаление». Вместо этого опишите ** отношение ** между сущностями, например 'user_groups_without',' rules_updated' и т. Д. Поиск хороших имен - это тяжело и стоит того! – mat

ответ

2

Да.

Узор вы описываете очень часто, и все серьезные Пролог системы корабля с мощными мета-сказуемых (т.е. предикаты, аргументы обозначают предикаты), которые позволяют легко описать это и много других общих ситуаций на гибкой основе, используя не более нескольких простых дополнительных определений для ваших конкретных отношений.

Предложение Ричарда О'Кифа для An elementary Prolog Library содержит описания и реализации многих таких предикатов, которые становятся все более доступными во всех основных реализациях Пролога, а также в Prologue for Prolog.

В частности, вы должны изучить:

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

Примечание, однако, что многие из описанных предикатов нечистой в том смысле, что они будут уничтожить декларативные свойства вашего кода. В отличие от истинных отношений, вы не сможете использовать их во всех направлениях  , сохраняя при этом логическую надежность.

Упражнение: Какой из трех предикатов, упомянутых выше, если таковые имеются, сохранить когда все остальное чисто, и, если они есть, не?

+1

Большое спасибо - это действительно помогло мне! –

Смежные вопросы