如果序列= [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()]
};
答案 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
}