Рассчитать дельту из списка - PullRequest
0 голосов
/ 01 сентября 2011

У меня есть этот список:

  • ADD X
  • ДОБАВИТЬ Y
  • УДАЛИТЬ Z
  • ADD X
  • НЕТ ДЕЙСТВИЙ Y

Мне нужны следующие результаты:

  • ADD X
  • НЕТ ДЕЙСТВИЙ Y
  • УДАЛИТЬ Z

Правила расчета дельты таковы: У меня есть 3 действия (ДОБАВИТЬ, УДАЛИТЬ, НЕТ ДЕЙСТВИЙ)

  1. ЛЮБОЕ ДЕЙСТВИЕ * НЕТ ДЕЙСТВИЯ = НЕТ ДЕЙСТВИЯ
  2. ДОБАВИТЬ * УДАЛИТЬ или УДАЛИТЬ * ДОБАВИТЬ = НЕТ ДЕЙСТВИЙ
  3. ЖЕ ДЕЙСТВИЕ * ЖЕ ДЕЙСТВИЕ = ЖЕ ДЕЙСТВИЕ

Проблема в том, что я реализую это с помощью функционального языка (XQuery). Я нашел логику, основанную на fn: Different-values. Но последнее правило (3) не выполняется.

Заранее спасибо !!

Ответы [ 2 ]

2 голосов
/ 02 сентября 2011

Вы не упомянули, какой процессор XQuery вы используете, но если у него есть хеш-карты, вы можете сделать это следующим образом (протестировано в MarkLogic Server):

let $seq := ("ADD X", "ADD Y", "REMOVE Z", "ADD X", "NO-ACTION Y")
let $map := map:map()
let $_ :=
  for $s in $seq 
  let $parts := fn:tokenize($s, " ")
  let $service := $parts[2]
  let $action := $parts[1]
  let $current-action := map:get($map, $service)
  return
    if ("NO-ACTION" = ($action, $current-action)) then
      map:put($map, $service, "NO-ACTION") (: rule 1 :)
    else if ("REMOVE" = ($action, $current-action)) then
      map:put($map, $service, "REMOVE") (: rule 2 :)
    else
      map:put($map, $service, $action) (: actions are the same -- rule 3 :)
for $service in map:keys($map)
return fn:concat(map:get($map, $service), " ", $service)

Возвращает

ADD X 
REMOVE Z 
NO-ACTION Y

Обратите внимание, что я сделал упрощающее предположение и изменил «НЕТ ДЕЙСТВИЯ» на «НЕТ ДЕЙСТВИЯ», ​​чтобы упростить анализ.

0 голосов
/ 06 сентября 2011

Наконец я нашел путь.Я надеюсь, что это хорошо.

Это мои первые эксперименты с XQuery, и мне нужно вспомнить, что у меня под пальцами и какие возможности предлагает этот язык.

Моя проблема в данных, которые пришлив. И я решил преобразовать информацию в структуру, которой я могу легко манипулировать.

Золотой кирпич, чтобы решить это, этот пример о группировании данных:

for $d in distinct-values(doc("order.xml")//item/@dept)
let $items := doc("order.xml")//item[@dept = $d]
order by $d
return <department code="{$d}">{
     for $i in $items
     order by $i/@num
     return $i
   }</department>

После этого я использовалэтот алгоритм: 0. Если количество действий == 1 -> выполнить первое действие 1. else Если существует почти ОДИН - НЕТ ДЕЙСТВИЙ -> НЕТ ДЕЙСТВИЙ (ПРАВИЛО 1) 2. else Если существует ДОБАВИТЬ и УДАЛИТЬ в одном списке -> НЕТДЕЙСТВИЕ (ПРАВИЛО 2) 3. иначе выполнить первое действие (равные действия)

Для этого я позаимствовал функцию из библиотеки functx:

declare function local:is-value-in-sequence( $value as xs:anyAtomicType? ,$seq as      xs:anyAtomicType* )  as xs:boolean {
 $value = $seq
 };

Простой, но эффективный.

Большое спасибо за все!

...