使用XQuery计算序列中的连续重复元素

时间:2015-02-24 08:03:48

标签: xpath functional-programming integration xquery osb

如果序列= [a a b c c c a d e e e g h h]

然后输出= [1 2 1 1 2 3 1 1 2 1 2 3 1 1 1 2]

尝试使用递归但没有运气...请帮助..感谢期待

注意:使用XQuery实现1.0

我失败的实现之一如下:

declare function local:test($sequence,$count){

for $counter in (1 to count($sequence))

let $maxIndex := count($sequence)

return

if (matches(subsequence($sequence,1,$maxIndex)[$counter],subsequence($sequence,1,$maxIndex)[$counter + +1])) then let $count := $count + 1 return $count[last()]

else let $count := 1 return $count[last()]


};

3 个答案:

答案 0 :(得分:4)

你是对的,递归是一种非常可行的方式。以下函数的作用是从头到尾遍历序列。然后,对于每个元素,它在local:count()中计算前面的元素是否与当前元素相同。如果是这样,它将递归调用该函数,否则重复序列结束并返回1。

最后,这个结果序列再次反转,以匹配传入序列的顺序。

declare function local:count($sequence, $pos) {
  if ($sequence[$pos - 1] = $sequence[$pos])
  then 1 + local:count($sequence, $pos - 1)
  else 1
};

declare function local:test($sequence){
  reverse(
    for $pos in reverse(1 to count($sequence))
    return local:count($sequence, $pos)
  )
};

let $test := ("a","a", "b", "c", "c", "c", "a", "d", "d", "e", "e", "e", "f", "g", "h", "h")
return local:test($test)

答案 1 :(得分:0)

我为我的问题找到了一个有效的解决方案。致谢:odie_63 @ http://odieweblog.wordpress.com/

declare namespace xf = "http://tempuri.org/OSBTestProject/Resources/XQuery/test/";

declare function local:sequence-group($seq as item()*) as item()*
{
   let $start-of-group :=
   fn:index-of(
     for $i in 1 to count($seq)
     let $prev := $seq[$i - 1]
     return if ($prev != $seq[$i] or not($prev)) then 1 else 0
   , 1
   )
   return
     for $i in 1 to count($seq)
     return $i - $start-of-group[. le $i][last()] + 1
};

declare function xf:test($test as xs:string) as xs:integer*
 {
let $test1 := tokenize($test, ',')
 return  local:sequence-group($test1)
};

declare variable $test as xs:string external;

xf:test($test)

输入:a,a,b,c,c,c,a,d,d,e,e,e,f,g,h,h

输出:1 2 1 1 2 3 1 1 2 1 2 3 1 1 1 2

答案 2 :(得分:0)

未经测试,但这应该有效,并且相当简单。

declare function local:test($sequence)
{
    for $item at $current-pos in $sequence
    let $different-pos :=
        last((0, $sequence[position() < $current-pos][. != $item]))
    return $current-pos - $different-pos
}