From mixich.andreas at gmail.com Sat Aug 1 05:06:47 2020 From: mixich.andreas at gmail.com (Andreas Mixich) Date: Sat, 1 Aug 2020 14:06:47 +0200 Subject: [xquery-talk] Purely recursive deduplication of sequence? Message-ID: <6a075651-c649-9918-0b8b-da5968380435@gmail.com> 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} ???????????? , ???????????? , ???????????? , array {"apples","oranges"} ???????????? , array {"apples","oranges"} ???????????? , ???????????? , array {"One",5,} ???????????? , array {3,7,"Hello World!"} ???????????? , array {3,7,"Hello World!"} ???????????? , map{'key':'value'} ???????????? , false() ???????????? , false() ???????????? , array {"One","lorem",,2,"Naomi"} ???????????? , array {"One", "Two", 3} ???????????? , array {"One","lorem",,2,"Naomi"} ???????????? , array {,map{'key':'value'},true()} ???????????? , false() ???????????? ) ? return local:dedupe-pairs($a3) serializes to: ? ["One","Two",3] ? ["One","Two",1] ? ["One","Two",3] ? ? ["apples","oranges"] ? ? ["One",5,] ? [3,7,"Hello World!"] ? map{"key":"value"} ? false ? ["One","lorem",,2,"Naomi"] ? ["One","Two",3] ? ["One","lorem",,2,"Naomi"] ? [,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 From christian.gruen at gmail.com Sat Aug 1 05:57:38 2020 From: christian.gruen at gmail.com (=?UTF-8?Q?Christian_Gr=C3=BCn?=) Date: Sat, 1 Aug 2020 14:57:38 +0200 Subject: [xquery-talk] Purely recursive deduplication of sequence? In-Reply-To: <6a075651-c649-9918-0b8b-da5968380435@gmail.com> References: <6a075651-c649-9918-0b8b-da5968380435@gmail.com> Message-ID: 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 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} > ???????????? , > ???????????? , > ???????????? , array {"apples","oranges"} > ???????????? , array {"apples","oranges"} > ???????????? , > ???????????? , array {"One",5,} > ???????????? , array {3,7,"Hello World!"} > ???????????? , array {3,7,"Hello World!"} > ???????????? , map{'key':'value'} > ???????????? , false() > ???????????? , false() > ???????????? , array {"One","lorem",,2,"Naomi"} > ???????????? , array {"One", "Two", 3} > ???????????? , array {"One","lorem",,2,"Naomi"} > ???????????? , array {,map{'key':'value'},true()} > ???????????? , false() > ???????????? ) > ? return local:dedupe-pairs($a3) > > serializes to: > > ? ["One","Two",3] > ? ["One","Two",1] > ? ["One","Two",3] > ? > ? ["apples","oranges"] > ? > ? ["One",5,] > ? [3,7,"Hello World!"] > ? map{"key":"value"} > ? false > ? ["One","lorem",,2,"Naomi"] > ? ["One","Two",3] > ? ["One","lorem",,2,"Naomi"] > ? [,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 From christian.gruen at gmail.com Sat Aug 1 06:21:10 2020 From: christian.gruen at gmail.com (=?UTF-8?Q?Christian_Gr=C3=BCn?=) Date: Sat, 1 Aug 2020 15:21:10 +0200 Subject: [xquery-talk] Purely recursive deduplication of sequence? In-Reply-To: References: <6a075651-c649-9918-0b8b-da5968380435@gmail.com> Message-ID: One more solution with fold-left (it?s faster than the recursive approach): declare function local:distinct-items($items as item()*) as item()* { fold-left($items, (), function($result, $item) { $result, $item[empty($result[deep-equal(., $item)])] }) }; local:distinct-items(('x', (1 to 1000000) ! 1, 'x')) On 8/1/20, Christian Gr?n wrote: > 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 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} >> ???????????? , >> ???????????? , >> ???????????? , array {"apples","oranges"} >> ???????????? , array {"apples","oranges"} >> ???????????? , >> ???????????? , array {"One",5,} >> ???????????? , array {3,7,"Hello World!"} >> ???????????? , array {3,7,"Hello World!"} >> ???????????? , map{'key':'value'} >> ???????????? , false() >> ???????????? , false() >> ???????????? , array {"One","lorem",,2,"Naomi"} >> ???????????? , array {"One", "Two", 3} >> ???????????? , array {"One","lorem",,2,"Naomi"} >> ???????????? , array {,map{'key':'value'},true()} >> ???????????? , false() >> ???????????? ) >> ? return local:dedupe-pairs($a3) >> >> serializes to: >> >> ? ["One","Two",3] >> ? ["One","Two",1] >> ? ["One","Two",3] >> ? >> ? ["apples","oranges"] >> ? >> ? ["One",5,] >> ? [3,7,"Hello World!"] >> ? map{"key":"value"} >> ? false >> ? ["One","lorem",,2,"Naomi"] >> ? ["One","Two",3] >> ? ["One","lorem",,2,"Naomi"] >> ? [,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 > From mixich.andreas at gmail.com Sat Aug 1 08:58:38 2020 From: mixich.andreas at gmail.com (Andreas Mixich) Date: Sat, 1 Aug 2020 17:58:38 +0200 Subject: [xquery-talk] Purely recursive deduplication of sequence? In-Reply-To: References: <6a075651-c649-9918-0b8b-da5968380435@gmail.com> Message-ID: <594d60e8-83d5-5f37-0e3a-c7c4dd1f3b8a@gmail.com> Am 01.08.2020 um 14:57 schrieb Christian Gr?n: Thank you so much for all three examples! Of course, in the end, I am going to take the one, which has the best performance. Do you expect it to be the `FLOWR` based or the `fold-left#3` based, you demonstrated in the follow-up? Still, I am glad to see this one, since it surprises me, as to how short this can be! My own ponderings started to get out of hand by adding more and more code - to no avail. That was when I gave up and just asked. > 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)))]) > ) > }; -- Goody Bye, Minden j?t, Mit freundlichen Gr??en, Andreas Mixich From christian.gruen at gmail.com Sat Aug 1 09:27:59 2020 From: christian.gruen at gmail.com (=?UTF-8?Q?Christian_Gr=C3=BCn?=) Date: Sat, 1 Aug 2020 18:27:59 +0200 Subject: [xquery-talk] Purely recursive deduplication of sequence? In-Reply-To: <594d60e8-83d5-5f37-0e3a-c7c4dd1f3b8a@gmail.com> References: <6a075651-c649-9918-0b8b-da5968380435@gmail.com> <594d60e8-83d5-5f37-0e3a-c7c4dd1f3b8a@gmail.com> Message-ID: > > Of course, in the end, I am going to take the one, which has the > best performance. Do you expect it to be the `FLOWR` based or > the `fold-left#3` based, you demonstrated in the follow-up? > Solutions with fold-left are usually the most efficient ones, but it also depends on the XQuery processor you use. Feel free to share your test results. -------------- next part -------------- An HTML attachment was scrubbed... URL: From mixich.andreas at gmail.com Sat Aug 15 07:08:34 2020 From: mixich.andreas at gmail.com (Andreas Mixich) Date: Sat, 15 Aug 2020 16:08:34 +0200 Subject: [xquery-talk] Wrap element constructor and output disappears In-Reply-To: References: Message-ID: <8e7aaf34-80d5-1f8a-6a79-693ad91e59f3@gmail.com> Ihe Onwuka wrote: > But if I try to wrap an element around that output like below nothing > is returned > |{ let $root := for > $prefix in in-scope-prefixes($root)[not(. = ('xml', 'xsi'))] return > namespace-uri-for-prefix($prefix,$root) ! value="{.}"/> } | > > So what is wrong and how do I wrap the output in a parameters element? > Not sure, whether such a late reply is of any use to you, sorry, I just discovered it now. I want to confirm, that it works with BaseX 9.4. The output I get is: ??? ??? ? ??? ? ??? -- Goody Bye, Minden j?t, Mit freundlichen Gr??en, Andreas Mixich