【问题标题】:Count consecutive repetitive element in a sequence using XQuery使用 XQuery 计算序列中的连续重复元素
【发布时间】:2015-02-24 08:03:48
【问题描述】:

如果序列 = [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]

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

注意:使用 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()]


};

【问题讨论】:

  • @tod : 加倍努力,但实际看起来有所不同,因为原始要求有所不同,但目标相同。
  • 似乎 $counter 是一个序列,因此它在匹配条件下返回一个序列,因此此实现失败。
  • 这个序列是否来自您的输入 XML?如果是,请出示此文件。
  • @MathiasMüller 这个序列作为 local:test(data($head1/*:Row/X),1) 传递给函数
  • @MathiasMüller $head 是一个外部变量,看起来像 a1b1c1

    额外

    a2b2 c2

    额外

    a2b2c3

    额外

    a2b2c4

    额外

    a3b3c3

    额外

标签: xpath functional-programming integration xquery osb


【解决方案1】:

你是对的,递归是一种非常可行的方式。以下函数的作用是从头到尾遍历序列。对于每个元素,它会计算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)

【讨论】:

  • 不,它没有用:我使用输入为:aabcccaddeeefghh 并得到输出:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  • 您没有修改函数local:count()local:test() 中的任何内容。好像您没有将序列传递给local:test()
  • 不,我传递了一个序列,为了重新澄清,我再次更改了代码:pastie.org/9980545 并传递了 a,a,b,c,c,c,a,d,d,e, e,e,f,g,h,h 和得到输出:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  • 很抱歉,您的说法不正确。如果您将 xs:string "a,a,b,c,c,c,a,d,d,e,e,e,f,g,h,h" 传递到您的 xs:OutToMod() 函数中,您将得到正确的结果 1 2 1 1 2 3 1 1 2 1 2 3 1 1 1 2。如果没有,你要么做错了,要么你的处理器行为不正确。
  • 可能是这样,我正在使用与 Oracle Enterprise Pack for Eclipse (11gR1 - 11.1.1.7.3) 捆绑在一起的 Xquery 引擎,它缺乏一些功能,并且经常偏离 W3 的实际建议。跨度>
【解决方案2】:

我的问题有一个可行的解决方案。致谢: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

【讨论】:

    【解决方案3】:

    未经测试,但这应该可以工作,而且相当简单。

    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
    }
    

    【讨论】:

      猜你喜欢
      • 2019-08-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-26
      • 1970-01-01
      • 2015-12-01
      • 1970-01-01
      • 2014-07-08
      • 1970-01-01
      相关资源
      最近更新 更多