问题描述
在此示例中,我有一个字符串$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变量很大,则使用适当的映射技术将它们绑定。