[xquery-talk] Purely recursive deduplication of sequence?
Christian Grün
christian.gruen at gmail.com
Sat Aug 1 05:57:38 PDT 2020
Hi Andreas,
Try this:
declare function local:distinct-items($items as item()*) as item()* {
let $h := head($items)
where exists($h)
let $t := tail($items)[not(deep-equal(., $h))]
return ($h, local:distinct-items($t))
};
If the FLWOR expression is avoided, it may increase the runtime:
declare function local:distinct-items($items as item()*) as item()* {
if (empty($items)) then () else (
head($items),
local:distinct-items(tail($items)[not(deep-equal(., head($items)))])
)
};
Hope this helps,
Christian
On 8/1/20, Andreas Mixich <mixich.andreas at gmail.com> wrote:
> Hello,
>
> I wonder, whether it could be possible to deduplicate a sequence by a
> purely recursive approach,
> without creating state in any form.
>
> What I have, so far, is only capable of removing consecutive dupes, so,
> nothing fancy.
>
> (:~
> Removes all consecutive duplicate items from a sequence, returning
> the deduped sequence.
>
> @param $items a sequence, that may contain duplicates
> @return a sequence, in which all 'pairs' have been 'singled'
> :)
> declare function local:dedupe-pairs($items as item()*) as item()* {
> if (count($items) <= 1)
> then $items
> else if (deep-equal(head($items), head(tail($items))))
> then local:dedupe-pairs(tail($items))
> else (
> head($items)
> , local:dedupe-pairs(tail($items))
> )
> };
>
> (: following sequence has 19 items :)
> let $a3 := (
> array {"One", "Two", 3}
> , array {"One", "Two", 1}
> , array {"One", "Two", 3}
> , <xml></xml>
> , <xml></xml>
> , array {"apples","oranges"}
> , array {"apples","oranges"}
> , <xml></xml>
> , array {"One",5,<xml></xml>}
> , array {3,7,"Hello World!"}
> , array {3,7,"Hello World!"}
> , map{'key':'value'}
> , false()
> , false()
> , array {"One","lorem",<xml></xml>,2,"Naomi"}
> , array {"One", "Two", 3}
> , array {"One","lorem",<xml></xml>,2,"Naomi"}
> , array {<xml></xml>,map{'key':'value'},true()}
> , false()
> )
> return local:dedupe-pairs($a3)
>
> serializes to:
>
> ["One","Two",3]
> ["One","Two",1]
> ["One","Two",3]
> <xml/>
> ["apples","oranges"]
> <xml/>
> ["One",5,<xml/>]
> [3,7,"Hello World!"]
> map{"key":"value"}
> false
> ["One","lorem",<xml/>,2,"Naomi"]
> ["One","Two",3]
> ["One","lorem",<xml/>,2,"Naomi"]
> [<xml/>,map{"key":"value"},true()]
> false
>
> However, this is not what I want. I want to understand, whether a
> function would be possible, that completely dedupes given sequence,
> like `fn:distinct-values#1`, however, for any kind of item, not just
> atomic ones:
>
> `local:distinct-items($items as item()*) as item()*`
>
> It should no use state in any form (typically creating and revolving
> a second list or sending a flag throughout recursion).
>
> Also, I do not want to use any manipulative functions (like fn:remove#2)
> and, ideally, no `FOR..IN..` construct.
>
> The deduped list would be purely the result of the recursive walk through
> the list, grown organically, so to say.
>
> Only, I can not come up with such a thing. Is there a way to do it?
>
> Thank you.
>
> --
> Goody Bye, Minden jót, Mit freundlichen Grüßen,
> Andreas Mixich
> _______________________________________________
> talk at x-query.com
> http://x-query.com/mailman/listinfo/talk
More information about the talk
mailing list