I am trying to loop over items and output number of occurrences for each one, but it outputs the same dictionary a number of times equal to the number of items. Is there a way same as using parentheses to just make the loops for let
statements. I know that XQuery is a functional language and that I can use group by
but it is not supported in marklogic.
xquery version "1.0-ml";
let $dict := map:map()
for $i in ('book1','book2','book2')
let $n := (if (map:contains($dict, $i)) then (map:get($dict, $i)) else (0))
let $dict1 := map:put($dict, $i, 1 $n)
return $dict
Output:
<map:map>
<map:entry key="book1">
<map:value xsi:type="xs:integer">1</map:value>
</map:entry>
<map:entry key="book2">
<map:value xsi:type="xs:integer">2</map:value>
</map:entry>
</map:map>
map as
XML
<map:map>
<map:entry key="book1">
<map:value xsi:type="xs:integer">1</map:value>
</map:entry>
<map:entry key="book2">
<map:value xsi:type="xs:integer">2</map:value>
</map:entry>
</map:map>
map as
XML
<map:map>
<map:entry key="book1">
<map:value xsi:type="xs:integer">1</map:value>
</map:entry>
<map:entry key="book2">
<map:value xsi:type="xs:integer">2</map:value>
</map:entry>
</map:map>
CodePudding user response:
In addition to the answer of @MadsHansen you could also use more functions:
xquery version "1.0-ml";
let $dict := map:map()
let $myvalues := ('book1','book2','book2')
let $_ :=
for $i in fn:distinct-values($myvalues)
return map:put($dict, $i, count(index-of($i, $myvalues)))
return $dict
(I picked the "frequency" function with the combination of count
and index-of
from another answer on stack overflow)
CodePudding user response:
You can let
a throwaway variable and then put the for loop FLWOR processing for that variable, then return the $dict
map:
xquery version "1.0-ml";
let $dict := map:map()
let $_ :=
for $i in ('book1','book2','book2')
let $n := if (map:contains($dict, $i)) then map:get($dict, $i) else 0
return map:put($dict, $i, 1 $n)
return $dict
Since map:put()
returns an empty sequence, you could also return a sequence with the for-loop processing and then the $dict
:
xquery version "1.0-ml";
let $dict := map:map()
return (
for $i in ('book1','book2','book2')
let $n := if (map:contains($dict, $i)) then map:get($dict, $i) else 0
return map:put($dict, $i, 1 $n),
$dict
)
A more concise version of the same processing:
xquery version "1.0-ml";
let $dict := map:map()
let $_ := ('book1','book2','book2') ! map:put($dict, ., 1 head((map:get($dict, .), 0)))
return $dict