map:group-by or map:build with a sequence of keys?

When map:group-by was introduced I found the restriction of a single key
instead of a sequence of keys unnecessarily restrictive (some people on
Slack agreed), the same appears in my view to be the case for the new
map:build, I think it could be easily adapted to handle a sequence of
keys by using e.g.

  fold-left($input, map{}, ->($map, $next) {

   fold-left($key($next), $map, ->($map, $key) {
    let $nextValue := $value($next) return
    if (map:contains($map, $key))
    then map:put($map, $key, $combine($map($key), $nextValue))
    else map:put($map, $key, $nextValue)})
  }
)

as the implementation body/definition of the result of

map:build(
$input    as item()*,
$key    as function(item()) as xs:anyAtomicType*    := fn:identity#1,
$value    as function(item()) as item()*    := fn:identity#1,
$combine    as function(item()*, item()*) as item()*    := fn:op(',')
) as map(*)


Use case in my view is the classical example of the XSLT 3 spec where in
e.g.

<titles>
     <title>A Beginner's Guide to <ix>Java</ix></title>
     <title>Learning <ix>XML</ix></title>
     <title>Using <ix>XML</ix> with <ix>Java</ix></title>
</titles>

you want to group the "title" elements by the "ix" child elements, with
the proposed change above that would give e.g.

map {
   "Java": (<title>A Beginner's Guide to <ix>Java</ix>
</title>, <title>Using <ix>XML</ix> with <ix>Java</ix>
</title>),
   "XML": (<title>Learning <ix>XML</ix>
</title>, <title>Using <ix>XML</ix> with <ix>Java</ix>
</title>)
}


XSLT 2/3 grouping always had this feature to allow an item in the
grouping population to belong to several groups, the above change would
give that same power to XPath/XQuery based grouping using map:build.

Received on Thursday, 13 October 2022 12:15:56 UTC