xsl-list
[Top] [All Lists]

Re: [xsl] XQuery/XPath 3.1: Node List to Node Set ("distinct nodes")

2021-12-29 09:25:24
Wow—this generated much more discussion than I anticipated.

For my requirements of the moment the order of the result node set is 
unimportant, so “$nodes intersect ()” seems like the least surprising solution 
(and I suspect I might have arrived at it if I’d spent a bit more time thinking 
about the problem, but it’s the holidays and I had things to do and places to 
be …).

I’ve never actually taken the time to understand how fold-left works, so this 
is an opportunity to learn.

From the functions and operators spec:

<lq>
Fold-left

Processes the supplied sequence from left to right, applying the supplied 
function repeatedly to each item in turn, together with an accumulated result 
value.
</lq>

So given this expression:

fold-left($nodes, (), function($a, $n) { $a, $n except $a })

I understand this to be iterating over $nodes from left to right, applying the 
function function($a, $n) to each node, where $a is the next node and $n is the 
accumulated value (being the result returned by the function on each 
invocation).

The “$a, $n except $a” in the function body constructs a new sequence of ($a, 
$n), excluding $a if it is already in $n. This sequence is then passed as the 
second parameter of the next invocation of the function. This has the effect of 
preserving the order of input node list.

If I have this right then it’s essentially equivalent to my original recursive 
solution but much, much simpler and of course usable directly as an XPath 
expression.

Cheers,

E.


_____________________________________________
Eliot Kimber
Sr Staff Content Engineer
O: 512 554 9368
M: 512 554 9368
servicenow.com<https://www.servicenow.com>
LinkedIn<https://www.linkedin.com/company/servicenow> | 
Twitter<https://twitter.com/servicenow> | 
YouTube<https://www.youtube.com/user/servicenowinc> | 
Facebook<https://www.facebook.com/servicenow>

From: Michael Kay mike(_at_)saxonica(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com>
Date: Wednesday, December 29, 2021 at 4:37 AM
To: xsl-list <xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com>
Subject: Re: [xsl] XQuery/XPath 3.1: Node List to Node Set ("distinct nodes")
[External Email]

Here is an improved (and shorter) version of the fold-left() solution:

fold-left($nodes, (), function($a, $n) { $a, $n except $a })

Michael Kay
Saxonica


On 28 Dec 2021, at 23:47, Michael Kay 
mike(_at_)saxonica(_dot_)com<mailto:mike(_at_)saxonica(_dot_)com> 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com<mailto:xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com>>
 wrote:

For a solution that delivers distinct nodes in order of first appearance, my 
preference would be

$nodes => fold-left((), function($all, $this) {if ($all intersect $this) then 
$all else ($all, $this)})

It's likely to be O(n^2) in most implementations, whereas Martin Honnen's 
solution is probably O(n log n) -- but this one is XPath rather than XQuery, 
and feels more elegant.

Michael Kay
Saxonica
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--
<Prev in Thread] Current Thread [Next in Thread>