Xquery按字符的第N次出现拆分字符串

时间:2014-05-12 21:05:26

标签: xquery

我需要一些帮助,通过特定字符的第N次出现来分割长字符串。例如

<string>1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27</string>

被第9个逗号分开 并成为

<string>1,2,3,4,5,6,7,8,9</string>
<string>10,11,12,13,14,15,16,17,18</string>
<string>19,20,21,22,23,24,25,26,27</string>

未指定原始字符串的长度,示例中的数字1-27可以是带空格的单词,但逗号是唯一的分隔符。

谢谢!

3 个答案:

答案 0 :(得分:3)

let $s := <string>1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27</string>
let $len := 9
let $tokens := tokenize($s, ',')
for $n in (1 to count($tokens) idiv $len)
return <string>{ 
  string-join(subsequence($tokens, $len * ($n - 1) + 1, $len), ',') 
}</string>

答案 1 :(得分:1)

进一步参考,这是使用XQuery 3.0的另一个解决方案。它不使用正则表达式,而是使用tumbling window

let $s := '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27'
for tumbling window $w in tokenize($s, ',')
    start at $start when true()
    end at $end when $end - $start eq 8
return <string>{$w}</string>

在我看来,这看起来像windows的模型用例。它具有非常好的可读性:使用翻滚窗口(与滑动窗口形成对比,滑动窗口在每个回合中仅在序列中进一步滑动一个元素,翻滚窗口从不重叠)并从序列的开头开始。如果窗口中有9个元素(即在开始和结束之间有8个元素),则结束一个窗口。

答案 2 :(得分:0)

如果您可以访问XQuery 3.0,还可以使用analyze-string(...)使用一些正则表达式foo:

let $string := '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27'
let $result := analyze-string($string, '(?:[^,]+,){8}[^,]+')
return $result/fn:match

请确认正则表达式中的重复次数比您要分区后的值的数量少一个;它类似于commata的值的数量,以及之后的单个值。

如果你还需要处理尾巴,例如。将字符串分成8个数字的元组时:

let $string := '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27'
let $result := analyze-string($string, '(?:[^,]+,){7}[^,]+')
return $result/(fn:match/string(), *[last()]/substring(., 2))