如何在XQuery中重复函数调用?

问题描述

在此示例中,我有一个字符串$text,并且想在其上调用四次fn:replace以得到结果"zyxw"

xquery version "1.0-ml";
let $text := "abcd"
let $patterns := ("a","b","c","d")
let $replaces := ("z","y","x","w")
for $i in (1 to fn:count($patterns))
  let $p := $patterns[$i]
  let $r := $replaces[$i]
  let $text := fn:replace($text,$p,$r)
  return $text

相反,我得到了序列:

("zbcd","aycd","abxd","abcw")

我明白为什么会这样。我只是不确定如何完成我在XQuery中要做的事情。我想要的JavaScript等效项是这样的:

'use strict';
let text = "abcd";
let patterns = ["a","d"];
let replaces = ["z","w"];
for(let i = 0,len = patterns.length; i < len; ++i){
  text = fn.replace(text,patterns[i],replaces[i]);
}
text

解决方法

XQuery中最自然的解决方案是使用递归:

declare function local:recurse($text,$patterns,$replaces) {
  let $text := fn:replace($text,fn:head($patterns),fn:head($replaces))
  let $remainder := fn:tail($patterns)
  return
    if (fn:exists($remainder)) then
      local:recurse($text,$remainder,fn:tail($replaces))
    else
      $text
};

let $text := "abcd"
let $patterns := ("a","b","c","d")
let $replaces := ("z","y","x","w")
return local:recurse($text,$replaces)

HTH!

,

尝试一些不同的方法:

for $i in (1 to fn:string-length($text))  
  let $target := substring($text,$i,1)
  let $fin := $replaces[index-of($patterns,$target) ]
return
concat($fin,"")

输出应为:

z y x w

这也适用于$text$patterns顺序不同的情况;例如"bdca"

,

是的,按照grtjn的建议,递归是一种合法的方式。换句话说,我只是对您的代码进行了一些小的调整以获得所需的输出。试试这个-

let $text := "abcd"
let $patterns := ("a","w")
let $replace-op :=
  for $i in (1 to fn:count($patterns))
  let $p := $patterns[$i]
  let $r := $replaces[$i]
  let $new-text := fn:replace($text,$p,$r)
  return xdmp:set($text,$new-text)
return $text

我建议,如果$ pattern和$ replaces变量很大,则使用适当的映射技术将它们绑定。