This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 29353 - Lossless map:merge
Summary: Lossless map:merge
Status: RESOLVED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XQuery 3.2 Use Cases and Requirements (show other bugs)
Version: Candidate Recommendation
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: Jonathan Robie
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-12-30 18:09 UTC by rxk2rxk
Modified: 2016-09-26 05:11 UTC (History)
2 users (show)

See Also:


Attachments

Description rxk2rxk 2015-12-30 18:09:11 UTC
Hi,

I am using map:merge to construct a map from smaller maps and would like to preserve values when the keys agree. For example, when calling

    map:merge((map:entry(0, "red"), (map:entry(1, "green"), map:entry(1, "blue")))

I would like to get back something like

    map { 0: "red", 1: ("green", "blue") }

The W3C specification is to drop "green" in favor of "blue".

While the desired behavior can be accomplished using XQuery syntax, the solution is not elegant and is relatively slow. Would it be possible to add an option to map:merge that will exhibit lossless merging?

Thanks,
Ron
Comment 1 Michael Kay 2015-12-31 08:22:49 UTC
Your desired function can be written

function f:merge-entries($m1, $m2) {
  map:merge(
    for $k in distinct-values((map:keys($m1), map:keys($m2))
    return map{$k : ($m1($k), $m2($k))}
  )
}

which doesn't feel inelegant to me, and if it's inefficient, that's an implementation problem.
Comment 2 Abel Braaksma 2015-12-31 15:28:18 UTC
I would agree that it'd be nice to have a map:merge that can do that. 

I.e., perhaps one that takes a second argument that is a higher order function which takes a sequence of map entries that contain the same key. However, writing such a function is trivial (Michael shows one approach, which can be made higher-order), which you can then use as a generic variant of map:merge.

I doubt that, considering the spec is in CR stage, new functions, or variants of functions can be added.
Comment 3 Abel Braaksma 2016-01-01 12:33:52 UTC
> I doubt that, considering the spec is in CR stage, new functions, or 
> variants of functions can be added.
Apologies, I see now that this was raised against XQ 3.2 Use Cases.
Comment 4 rxk2rxk 2016-01-01 22:09:09 UTC
Ok. But it gets more complicated if the merge is done repeatedly in a loop over a large database (e.g., 200,000 clinical trials). Adding an option in Java should be straightforward and the most efficient solution IMHO. Otherwise, feel free to close this suggestion.
Comment 5 Michael Kay 2016-09-26 05:11:15 UTC
This can now be done in 3.1 using the syntax

map:merge($maps, map{"duplicates":"combine"})