XQuery:映射到序列数组

时间:2019-03-19 12:21:28

标签: xquery

我有以下地图:

let $input := map { 'a-key': 'a-value', 'b-key': ['b-value-1', 'b-value-2'] }

b-key数组的长度可以变化,也可以不存在; a-key可以存在或不存在)

我需要创建以下数组:

[ ('a', 'b', 'b'), 'a-value', 'b-value-1', 'b-value-2' ]

第一个序列中b的数量应与b-value s的数量相对应。

我几乎尝试了iterating / map:for-each的每种组合,等等,该数组最终以太多的嵌套或完全平坦的方式结束了。

(n.b。数组将使用fn:apply传递给函数-而不是我的!因此必须采用这种形式)

2 个答案:

答案 0 :(得分:2)

构建包含动态构建的序列的数组似乎很困难,我认为您首先需要将序列构建为变量,然后使用方括号数组构造函数[$seq]来构建具有序列的数组作为单个项目。然后,您可以array:join其他值:

let $input := map { 'a-key': 'a-value', 'b-key': ['b-value-1', 'b-value-2'] }
let $seq := ($input?a-key!'a', (1 to array:size($input?b-key))!'b')
return 
    array:join(([$seq], array {$input?a-key, $input?b-key?* }))

https://xqueryfiddle.liberty-development.net/nbUY4ku/2

答案 1 :(得分:1)

If you are comfortable with the functional-programming side of XQuery, you can create the whole output in two nested "loops" (i.e. folds), one over the keys and the other one over those values that are arrays:

(: the input :)
let $input := map { 'a-key': 'a-value', 'b-key': ['b-value-1', 'b-value-2'] }

(: utility function that adds a single key/value pair to the output array :)
let $update-arr :=
    function($arr, $k, $v) {
      array:append(array:put($arr, 1, ($arr(1), $k)), $v)
    }

(: nested folds over keys and values :)
return fold-left(map:keys($input), [()], function($arr, $key) {
  let $k := substring-before($key, '-key')
  let $val := $input($key)
  return typeswitch($val)
    case array(*)
      return array:fold-left($val, $arr, function($arr2, $v) {
        $update-arr($arr2, $k, $v)
      })
    default
      return $update-arr($arr, $k, $val)
})

You can even abbreviate the array(*) case as return array:fold-left($val, $arr, $update-arr(?, $k, ?)) if you want.

The result is [("a", "b", "b"), "a-value", "b-value-1", "b-value-2"] as expected.