开发者

Calculate a delta from list

I have this list:

  • ADD X
  • ADD Y
  • REMOVE Z
  • ADD X
  • NO ACTION Y

I need of this results:

  • ADD X
  • NO ACTION Y
  • REMOVE Z

The rules to calculate the delta are these: I have 3 action (ADD, REMOVE, NO ACTION)

  1. ANY ACTION * NO ACTION = NO ACTION
  2. ADD * REMOVE or REMOVE * ADD = NO ACTION
  3. SAME ACTION * SAME ACTION = SAME ACTION

The problem is that I implement this with a functional language (XQuery). I found a logic, based on fn:distinct-values. But the last rule (3) is unsa开发者_高级运维tisfied.

Thanks in advance!!


You didn't mention what XQuery processor you are using, but if it has hashmaps, you can do it this way (tested in 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)

Returns

ADD X 
REMOVE Z 
NO-ACTION Y

Note that I made a simplifying assumption and changed "NO ACTION" to "NO-ACTION" to make the parsing simpler.


Finally I found the way. I hope that this is good.

These are my first experiments with XQuery and I need to remeber what I have under my fingers and what possibilities this language offer.

My problem is data that came in. And I decide to transformate the information in a structure that can I easily manipulate.

A golden brick to solve this is this example about grouping data :

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>

After this I used this algorithm: 0. If the count of action == 1 -> take first action 1. else If exist almost ONE - NO ACTION -> NO ACTION (RULE 1) 2. else If exist ADD and REMOVE in same list -> NO ACTION (RULE 2) 3. else take the first action (equal actions)

For this I borrowed a function from functx library:

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

Simple but effective.

Thanks a lot for all!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜