Returns a map that combines the entries from a number of existing maps.
map:merge
( $maps
as map(*)*
map(*)
map:merge
( $maps
as map(*)*
,$options
as map(*)
map(*)
The function map:merge
returns a map that
is formed by combining the contents of the maps supplied in the $maps
argument.
Informally, the supplied maps are combined as follows:
There is one entry in the returned map for each distinct key present in the union of the input maps, where two keys are distinct if they are not the same key .
If there are duplicate keys, that is, if two or more maps contain entries having the
same key, then the way this is handled is
controlled by the second ($options
) argument.
The definitive specification is as follows.
The effect of calling the single-argument function is the same as the effect of
calling the two-argument function with an empty map as the value of $options
.
The $options
argument can be used to control the way in which duplicate keys are handled.
The option parameter conventions apply.
The entries that may appear in the $options
map are as follows:
$maps
contain entries with key values
K1 and K2 where K1 and K2 are the
same key.
xs:string
use-first
An error is raised if duplicate keys are encountered.
If duplicate keys are present, all but the first of a set of duplicates are ignored,
where the ordering is based on the order of maps in the $maps
argument.
If duplicate keys are present, all but the last of a set of duplicates are ignored,
where the ordering is based on the order of maps in the $maps
argument.
If duplicate keys are present, all but one of a set of duplicates are ignored,
and it is implementation-dependent
which one is retained.
If duplicate keys are present, the result map includes an entry for the key whose
associated value is the sequence-concatenation of all the values associated with the key,
retaining order based on the order of maps in the $maps
argument.
The key value in the result map that corresponds to such a set of duplicates must
be the same key as each of the duplicates, but it is
otherwise unconstrained: for example if the duplicate keys are xs:byte(1)
and xs:short(1)
, the key in the result could legitimately be xs:long(1)
.
The result of the function call map:merge($MAPS, $OPTIONS)
is defined to be consistent with the result of the expression:
let $FOJS0003 := QName("http://www.w3.org/2005/xqt-errors", "FOJS0003"), $duplicates-handler := map { "use-first": function($a, $b) {$a}, "use-last": function($a, $b) {$b}, "combine": function($a, $b) {$a, $b}, "reject": function($a, $b) {fn:error($FOJS0003)}, "use-any": function($a, $b) {fn:random-number-generator()?permute(($a, $b))[1]} }, $combine-maps := function($A as map(*), $B as map(*), $deduplicator as function(*)) { fn:fold-left(map:keys($B), $A, function($z, $k){ if (map:contains($z, $k)) then map:put($z, $k, $deduplicator($z($k), $B($k))) else map:put($z, $k, $B($k)) }) } return fn:fold-left($MAPS, map{}, $combine-maps(?, ?, $duplicates-handler(($OPTIONS?duplicates, "use-first")[1]))
By way of explanation, $combine-maps
is a function that combines
two maps by iterating over the keys of the second map, adding each key and its corresponding
value to the first map as it proceeds. The second call of fn:fold-left
in the return
clause then iterates over the maps supplied in the call
to map:merge
, accumulating a single map that absorbs successive maps
in the input sequence by calling $combine-maps
.
This algorithm processes the supplied maps in a defined order, but processes the keys within each map in implementation-dependent order.
The use of fn:random-number-generator
represents one possible conformant
implementation for "duplicates":"use-any"
, but it is not the only conformant
implementation and is not intended to be a realistic implementation. The purpose of this
option is to allow the implementation to use whatever strategy is most efficient; for example,
if the input maps are processed in parallel, then specifying "duplicates":"use-any"
means that the implementation does not need to keep track of the original order of the sequence of input
maps.
let $week := map{0:"Sonntag", 1:"Montag", 2:"Dienstag",
3:"Mittwoch", 4:"Donnerstag", 5:"Freitag", 6:"Samstag"}
The expression map:merge(())
returns map{}
.
The expression map:merge((map:entry(0, "no"), map:entry(1, "yes")))
returns map{0:"no", 1:"yes"}
.
The expression map:merge(($week, map{7:"Unbekannt"}))
returns map{0:"Sonntag", 1:"Montag", 2:"Dienstag", 3:"Mittwoch", 4:"Donnerstag",
5:"Freitag", 6:"Samstag", 7:"Unbekannt"}
.
The expression map:merge(($week, map{6:"Sonnabend"}), map{"duplicates":"use-last"})
returns map{0:"Sonntag", 1:"Montag", 2:"Dienstag", 3:"Mittwoch", 4:"Donnerstag",
5:"Freitag", 6:"Sonnabend"}
.
The expression map:merge(($week, map{6:"Sonnabend"}), map{"duplicates":"use-first"})
returns map{0:"Sonntag", 1:"Montag", 2:"Dienstag", 3:"Mittwoch", 4:"Donnerstag",
5:"Freitag", 6:"Samstag"}
.
The expression map:merge(($week, map{6:"Sonnabend"}), map{"duplicates":"combine"})
returns map{0:"Sonntag", 1:"Montag", 2:"Dienstag", 3:"Mittwoch", 4:"Donnerstag",
5:"Freitag", 6:("Samstag", "Sonnabend")}
.
An error is raised if the value of
$options
indicates that duplicates are to be rejected, and a duplicate key is encountered.
An error is raised if the value of
$options
includes an entry whose key is defined
in this specification, and whose value is not a permitted value for that key.
If the input is an empty sequence, the result is an empty map.
If the input is a sequence of length one, the result map is indistinguishable from the supplied map.
There is no requirement that the supplied input maps should have the same or compatible
types. The type of a map (for example map(xs:integer, xs:string)
) is
descriptive of the entries it currently contains, but is not a constraint on how the map
may be combined with other maps.