I want to iterate开发者_开发知识库 over a sequence in xquery and grab 2 elements at a time. What is the easiest way to do this?
XQuery 3.0 Solution
For this and more complex paging use cases the Window Clause has been created in XQuery 3.0. But, it is not yet supported by many XQuery processors.
Windowing example
Here is a working example that you could execute for example on try.zorba :
for tumbling window $pair in (2, 4, 6, 8, 10, 12, 14)
start at $s when fn:true()
end at $e when $e - $s eq 1
return <window>{ $pair }</window>
Result
<window>2 4</window><window>6 8</window><window>10 12</window><window>14</window>
One option is to iterate over all items and just take the items once the items reach the divisor, in this case 2. The one downside is that you won't reach the last group of items if the items aren't even multiples of the divisor. For instance, the last element of a sequence with an odd number of elements will not be returned with this approach.
for $item at $index in $items
return
if ($item mod 2 = 0) then
($items[$index - 1], $items[$index])
else
()
Another option is to use mod and the index of the item. Using this approach you can make certain to include all elements in the $items sequence by adding one less than the number of items in your group to the count.
let $group-size := 2
return
for $index in (1 to fn:count($items)+($group-size - 1))[. mod $group-size = 0]
return
($items[$index - 1] , $items[$index])
let $s := ("a","b","c","d","e","f")
for $i in 1 to xs:integer(count($s) div 2)
return
<pair>
{($s[$i*2 - 1],$s[$i*2])}
</pair>
returns
<pair>a b</pair>
<pair>c d</pair>
<pair>e f</pair>
for $item at $index in $items
return
(
if ($index mod 2 eq 0) then
(
$items[xs:integer(xs:integer($index) - 1)], $items[xs:integer($index)]
)
else
()
)
精彩评论