Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps while retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says "The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and testing confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks! Graydon
Hi Graydon, have a look here https://github.com/xokomola/fold/blob/dbb79c60a7356e32a0994e581ad4f7f5377ddc...
hope it helps
--Marc
On 15 jul. 2015, at 20:01, Graydon Saunders graydonish@gmail.com wrote:
Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps while retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says "The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and testing confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks! Graydon
Looking at that code again I think it should be rewritten to use map:for-each it's too convoluted, but it probably gives you an idea of how to proceed. Here's a test that shows how it works. https://github.com/xokomola/fold/blob/dbb79c60a7356e32a0994e581ad4f7f5377ddc... --Marc
On 15 jul. 2015, at 21:51, Marc van Grootel marc.van.grootel@gmail.com wrote:
Hi Graydon, have a look here https://github.com/xokomola/fold/blob/dbb79c60a7356e32a0994e581ad4f7f5377ddc...
hope it helps
--Marc
On 15 jul. 2015, at 20:01, Graydon Saunders graydonish@gmail.com wrote:
Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps while retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says "The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and testing confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks! Graydon
Hi Marc --
That looks very helpful.
(Just as soon as I get over feeling like a cabbage for forgetting about fold-left()!)
thanks! Graydon
On Wed, Jul 15, 2015 at 3:51 PM, Marc van Grootel < marc.van.grootel@gmail.com> wrote:
Hi Graydon, have a look here https://github.com/xokomola/fold/blob/dbb79c60a7356e32a0994e581ad4f7f5377ddc...
hope it helps
--Marc
On 15 jul. 2015, at 20:01, Graydon Saunders graydonish@gmail.com wrote:
Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps while retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says "The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and testing confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks! Graydon
Van: Rob Stapper [mailto:r.stapper@lijbrandt.nl] Verzonden: donderdag 16 juli 2015 8:48 Aan: 'Graydon Saunders' Onderwerp: RE: [basex-talk] Union of maps?
Hoi Graydon,
Here’s one of my map-extensions. This one I use for merging maps.
It’s also an example of how to create your own high-order-functions.
Hopes is it helps.
Cheers,
Rob Stapper
declare function ext.map:merge
( $sourceMap as map(*)
, $targetMap as map(*)
, $updateFunction as function(*)
) as map(*)
{
fold-left( map:keys( $sourceMap)
, $targetMap
, function( $targetMap
, $key
)
{
map:put( $targetMap
, $key
, $updateFunction( map:get( $sourceMap, $key)
, map:get( $targetMap, $key)
)
)
}
)
} ;
Van: basex-talk-bounces@mailman.uni-konstanz.de [mailto:basex-talk-bounces@mailman.uni-konstanz.de] Namens Graydon Saunders Verzonden: woensdag 15 juli 2015 20:01 Aan: BaseX Onderwerp: [basex-talk] Union of maps?
Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps while retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says
"The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and testing confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks!
Graydon
--- Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. https://www.avast.com/antivirus
Van: Rob Stapper [mailto:r.stapper@lijbrandt.nl] Verzonden: donderdag 16 juli 2015 9:08 Aan: 'Graydon Saunders' Onderwerp: RE: [basex-talk] Union of maps?
Just as Marc: after looking at the code I found it needed tweeking ;-)
Here’s a tweeked version.
Succes,
Rob
declare function XQR.map:merge
( $sourceMap as map(*)
, $targetMap as map(*)
, $updateFunction as function(*)
) as map(*)
{
fold-left( map:keys( $sourceMap)
, $targetMap
, function( $targetMap
, $key
)
{
let $go :=
function( $sourceEntry
)
{
item:exists( map:get( $targetMap
, $key
)
, function( $targetEntry
)
{
map:put( $targetMap
, $key
, $updateFunction( $sourceEntry
, $targetEntry
)
)
}
, map:put( $targetMap
, $key
, $sourceEntry
)
)
}
return $go( map:get( $sourceMap
, $key
)
)
}
)
} ;
Plus bonus:
declare %basex:inline function item:exists
( $item
, $existProcessor
, $emptyValue
)
{ if ( exists( $item))
then $existProcessor( $item)
else $emptyValue
} ;
Van: basex-talk-bounces@mailman.uni-konstanz.de [mailto:basex-talk-bounces@mailman.uni-konstanz.de] Namens Graydon Saunders Verzonden: woensdag 15 juli 2015 20:01 Aan: BaseX Onderwerp: [basex-talk] Union of maps?
Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps while retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says
"The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and testing confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks!
Graydon
--- Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. https://www.avast.com/antivirus
Or, retweeked and made for multiple maps (@ Marc thanx for the inspiration)
declare function XQR.map:merge
( $mapSet as map(*)*
, $mergeFunction as function(*)
) as map(*)
{
fold-left( $mapSet
, map {}
, function( $targetMap
, $sourceMap
)
{
map:merge(( $targetMap
, $sourceMap
, for-each( map:keys( $targetMap)[ . = map:keys( $sourceMap)]
, function( $key
)
{
map:entry( $key
, $mergeFunction( map:get( $targetMap, $key)
, map:get( $sourceMap, $key)
)
)
}
)
))
}
)
} ;
Use:
xqr.map:merge( ( map { 'a' : ( 1,2,3,4)
, 'b' : ( 4,5,6,7)
}
, map { 'b' : ( 6,7,8,9)
, '7' : ( 'x', 'y', 'z')
}
, map { 'b' : ( 9,10,12)
, '7' : ( 'x', 'y', 'p')
}
)
, function( $data1
, $data2
)
{
distinct-values(( $data1, $data2))
}
) ! map:serialize( .)
You’re welcome,
Rob
Van: basex-talk-bounces@mailman.uni-konstanz.de [mailto:basex-talk-bounces@mailman.uni-konstanz.de] Namens Graydon Saunders Verzonden: woensdag 15 juli 2015 20:01 Aan: BaseX Onderwerp: [basex-talk] Union of maps?
Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps while retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says
"The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and testing confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks!
Graydon
--- Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. https://www.avast.com/antivirus
Wow.
Thanks, Rob! That about solves the problem.
On Fri, Jul 17, 2015 at 4:01 AM, Rob Stapper r.stapper@lijbrandt.nl wrote:
Or, retweeked and made for multiple maps (@ Marc thanx for the inspiration)
declare function XQR.map:merge
( $mapSet as map(*)* , $mergeFunction as function(*) ) as map(*) { fold-left( $mapSet , map {} , function( $targetMap , $sourceMap ) { map:merge(( $targetMap , $sourceMap , for-each( map:keys( $targetMap)[
. = map:keys( $sourceMap)]
, function( $key ) { map:entry(
$key
,
$mergeFunction( map:get( $targetMap, $key)
, map:get( $sourceMap, $key)
)
) } ) )) } ) } ;
Use:
xqr.map:merge( ( map { 'a' : ( 1,2,3,4)
, 'b' : ( 4,5,6,7) } , map { 'b' : ( 6,7,8,9) , '7' : ( 'x', 'y', 'z') } , map { 'b' : ( 9,10,12) , '7' : ( 'x', 'y', 'p') } ) , function( $data1 , $data2 ) { distinct-values(( $data1, $data2)) } ) ! map:serialize( .)
You’re welcome,
Rob
*Van:* basex-talk-bounces@mailman.uni-konstanz.de [mailto: basex-talk-bounces@mailman.uni-konstanz.de] *Namens *Graydon Saunders *Verzonden:* woensdag 15 juli 2015 20:01 *Aan:* BaseX *Onderwerp:* [basex-talk] Union of maps?
Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps while retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says
"The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and testing confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks!
Graydon
[image: Avast logo] https://www.avast.com/antivirus
Dit e-mailbericht is gecontroleerd op virussen met Avast antivirussoftware. www.avast.com https://www.avast.com/antivirus
Hi Graydon,
here is one more aproach for (it's not so flexible as the functional approach, though):
declare function local:merge($maps as map(*)*) as map(*) { map:merge( for $key in distinct-values($maps ! map:keys(.)) return map { $key: ($maps ! .($key)) } ) };
local:merge(( map { 'A': 1, 'B': 2 }, map { 'A': 3, 'C': 4 } ))
Cheers, Christian
On Wed, Jul 15, 2015 at 8:01 PM, Graydon Saunders graydonish@gmail.com wrote:
Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps while retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says "The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and testing confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks! Graydon
Thank you!
Are these easy enough that a map:union() function operating on a sequence of maps isn't something to ask for in the next spec iteration?
-- Graydon
On Fri, Jul 17, 2015 at 4:18 AM, Christian Grün christian.gruen@gmail.com wrote:
Hi Graydon,
here is one more aproach for (it's not so flexible as the functional approach, though):
declare function local:merge($maps as map(*)*) as map(*) { map:merge( for $key in distinct-values($maps ! map:keys(.)) return map { $key: ($maps ! .($key)) } ) };
local:merge(( map { 'A': 1, 'B': 2 }, map { 'A': 3, 'C': 4 } ))
Cheers, Christian
On Wed, Jul 15, 2015 at 8:01 PM, Graydon Saunders graydonish@gmail.com wrote:
Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps
while
retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says "The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and testing confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks! Graydon
Are these easy enough that a map:union() function operating on a sequence of maps isn't something to ask for in the next spec iteration?
Maybe yes. Feel free to propose it on the W3 issue tracker [1]. The talk@x-query.com mailing list may be another place to discuss this.
Best, Christian
[1] https://www.w3.org/Bugs/Public/describecomponents.cgi?product=XPath%20%2F%20...
On Fri, Jul 17, 2015 at 4:18 AM, Christian Grün christian.gruen@gmail.com wrote:
Hi Graydon,
here is one more aproach for (it's not so flexible as the functional approach, though):
declare function local:merge($maps as map(*)*) as map(*) { map:merge( for $key in distinct-values($maps ! map:keys(.)) return map { $key: ($maps ! .($key)) } ) };
local:merge(( map { 'A': 1, 'B': 2 }, map { 'A': 3, 'C': 4 } ))
Cheers, Christian
On Wed, Jul 15, 2015 at 8:01 PM, Graydon Saunders graydonish@gmail.com wrote:
Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps while retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says "The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and testing confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks! Graydon
talk@x-query.com says "too late for 3.1 (for a two-liner)" which is fair enough.
The Michael Kay version of the 2-liner looks like:
return map:merge( for $k in distinct-values($maps!map:keys(.)) return map:entry($k, $maps?($k)) )
Your version looks like: map:merge( for $key in distinct-values($maps ! map:keys(.)) return map { $key: ($maps ! .($key)) } )
I feel like I ought to update the docs with one or both but I don't understand the syntax in the return statement of either!
Any chance of getting either or both expanded for the easily-bewildered?
On Sat, Jul 18, 2015 at 8:19 AM, Christian Grün christian.gruen@gmail.com wrote:
Are these easy enough that a map:union() function operating on a
sequence of
maps isn't something to ask for in the next spec iteration?
Maybe yes. Feel free to propose it on the W3 issue tracker [1]. The talk@x-query.com mailing list may be another place to discuss this.
Best, Christian
[1] https://www.w3.org/Bugs/Public/describecomponents.cgi?product=XPath%20%2F%20...
On Fri, Jul 17, 2015 at 4:18 AM, Christian Grün <
christian.gruen@gmail.com>
wrote:
Hi Graydon,
here is one more aproach for (it's not so flexible as the functional approach, though):
declare function local:merge($maps as map(*)*) as map(*) { map:merge( for $key in distinct-values($maps ! map:keys(.)) return map { $key: ($maps ! .($key)) } ) };
local:merge(( map { 'A': 1, 'B': 2 }, map { 'A': 3, 'C': 4 } ))
Cheers, Christian
On Wed, Jul 15, 2015 at 8:01 PM, Graydon Saunders <graydonish@gmail.com
wrote:
Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps while retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says "The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and
testing
confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks! Graydon
Hi Graydon,
The solutions look similar indeed. Here is an more verbose writing, I hope it's helpful?
map:merge( (: select distinct keys :) for $key in distinct-values( for $map in $maps return map:keys($map) ) (: create new map entry with all values :) return map { $key : for $map in $maps return $map($key) } )
I recommend you to have a closer look at our Wiki article on XQuery 3.1 [1] and, possibly, XQuery 3.0 [2]. We tried to summarize the new language features in a simple and concise manner.
Cheers, Christian
[1] http://docs.basex.org/wiki/XQuery_3.1 [2] http://docs.basex.org/wiki/XQuery_3.0
return map:merge( for $k in distinct-values($maps!map:keys(.)) return map:entry($k, $maps?($k)) )
Your version looks like: map:merge( for $key in distinct-values($maps ! map:keys(.)) return map { $key: ($maps ! .($key)) } )
I feel like I ought to update the docs with one or both but I don't understand the syntax in the return statement of either!
Any chance of getting either or both expanded for the easily-bewildered?
On Sat, Jul 18, 2015 at 8:19 AM, Christian Grün christian.gruen@gmail.com wrote:
Are these easy enough that a map:union() function operating on a sequence of maps isn't something to ask for in the next spec iteration?
Maybe yes. Feel free to propose it on the W3 issue tracker [1]. The talk@x-query.com mailing list may be another place to discuss this.
Best, Christian
[1] https://www.w3.org/Bugs/Public/describecomponents.cgi?product=XPath%20%2F%20...
On Fri, Jul 17, 2015 at 4:18 AM, Christian Grün christian.gruen@gmail.com wrote:
Hi Graydon,
here is one more aproach for (it's not so flexible as the functional approach, though):
declare function local:merge($maps as map(*)*) as map(*) { map:merge( for $key in distinct-values($maps ! map:keys(.)) return map { $key: ($maps ! .($key)) } ) };
local:merge(( map { 'A': 1, 'B': 2 }, map { 'A': 3, 'C': 4 } ))
Cheers, Christian
On Wed, Jul 15, 2015 at 8:01 PM, Graydon Saunders graydonish@gmail.com wrote:
Hi --
In BaseX 8.2.1, I have a bunch of maps; the maps may have some overlap of key values. I would like to merge/find the union of all of these maps while retaining all the values associated with each key in the resulting map-of-all-maps. (Combined map? Any word can be wrong, here! :)
map:merge() doesn't do this; http://docs.basex.org/wiki/Map_Module#map:merge says "The associated value for each such key is taken from the last map in the input sequence $input that contains an entry with this key." and testing confirms this.
Is there a straightforward way to do this that I'm missing?
Thanks! Graydon
basex-talk@mailman.uni-konstanz.de