I'm using a map
for counting the number occurrences of, for example, each possible value of the attr
attribute of the elem
nodes:
<root>
<elem attr="a"/>
<elem attr="b"/>
<elem attr="b"/>
<elem />
<elem attr="a"/>
<elem attr="c"/>
<elem attr="b"/>
</root>
fold-left(
//elem/@attr,
map{},
function($m,$a) {map:put($m, $a, sum((1, $m($a))))}
)
Resulting map:
{
"a": 2,
"b": 3,
"c": 1
}
Now, using this map
, I would like to sort the integer values in descending order and emit their associated key. The expected "output" would be:
b
a
c
How can I do it?
If you store the map in a variable then it's possible to call fn:sort
on the keys while using the associated values as "sort keys":
let
$map := map{ "a": 2, "b": 3, "c": 1 }
return
$map => map:keys() => sort((), function($key) { -$map($key) })
(:
$map => map:keys() => sort((), $map) => reverse()
:)
b
a
c
You can also define a map:sort
function for maps, which would return a sequence of keys:
function(
$map as map(*),
$collation as xs:string?,
$valuate as function(xs:anyAtomicType, item()*) as xs:anyAtomicType*
) as xs:anyAtomicType*
{
sort(
map:keys($map),
$collation,
function($key) { $valuate($key, $map($key)) }
)
}
let $map:sort := function (...) {...}
return
map{ "a": 2, "b": 3, "c": 1 }
=> $map:sort((), function($k,$v) { -$v })