XQuery 字典中的 For 循环

For loop in dictionary in XQuery

我试图遍历项目并输出每个项目的出现次数,但它输出相同字典的次数等于项目的数量。有没有一种方法与使用括号相同,只是为 let 语句制作循环。我知道 XQuery 是一种函数式语言,我可以使用 group by 但 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

输出:

<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>

你可以let一个throwaway变量,然后对那个变量进行for循环FLWOR处理,然后return $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

由于 map:put() return 是一个空序列,您还可以 return 一个序列,其中包含 for-loop 处理,然后是 $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
)

相同处理的更简洁版本:

xquery version "1.0-ml";
let $dict := map:map()
let $_ := ('book1','book2','book2') ! map:put($dict, ., 1 + head((map:get($dict, .), 0)))
return $dict

除了@MadsHansen的回答你还可以使用更多的功能:

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

(我从 another answer on stack overflow 中选择了 countindex-of 组合的“频率”函数)