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)
- ANY ACTION * NO ACTION = NO ACTION
- ADD * REMOVE or REMOVE * ADD = NO ACTION
- 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!
精彩评论