Last active
August 29, 2015 14:02
-
-
Save adamretter/a198305a2219e3766e92 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
xquery version "3.0"; | |
module namespace ranges = "http://github.com/adamretter/ranges"; | |
(:~ | |
: Produces sequences of ranges ($from, $to) | |
: which span a $range-size | |
: all the way from $range-from upto $range-to | |
: | |
: This can be very useful when working | |
: with pagination of results to calculate | |
: the result subsequences per-page. | |
: | |
: For example: | |
: local:range-intervals(1, 22, 5, 0.25) | |
: would effectively produce (once the resulting | |
: functions are invoked): | |
: (1,5) (6,10) (11, 15) (16, 22) | |
: Note that the last range has a size larger than 5 | |
: as the $oversize-threshold was set to 25% i.e. 0.25. | |
: | |
: If you do not want an oversized last range, you | |
: can set the $oversize-threshold to 0% e.g.: | |
: local:range-intervals(1, 22, 5, 0) | |
: would produce: | |
: (1,5) (6,10) (11, 15) (16, 20) (21, 22) | |
: | |
: @param $range-from The bottom of the range to start from | |
: @param $range-to The top of the range to produce to | |
: @param $range-size The size of each range | |
: @param $oversize-threshold A percentage expressed as a decimal between | |
: 0 and 1. If greater than 0, then the last range may be upto | |
: $oversize-threshold bigger than preceding ranges. This allows you to | |
: create a fat last range rather than creating another range which contains | |
: perhaps just a few entries. | |
: | |
: @return A sequence of functions. Each function itself | |
: returns a sequence ($from, $to) | |
:) | |
declare function ranges:range-intervals($range-from as xs:integer, $range-to as xs:integer, $range-size as xs:integer, $oversize-threshold as xs:decimal) | |
as (function() as xs:integer+)+ { | |
let $absolute-intervals := $range-to idiv $range-size | |
let $intervals-modulus := $range-to mod $range-size | |
let $actual-threshold := $range-size * $oversize-threshold | |
let $oversize-last-interval := $intervals-modulus le $actual-threshold and $absolute-intervals gt 0 | |
return | |
( | |
for $range in ($range-from - 1 to $absolute-intervals - 1) | |
let $last := $range eq $absolute-intervals - 1 | |
return | |
function() { | |
let $from := $range * $range-size + 1 | |
let $to := if($last and $oversize-last-interval and $intervals-modulus > 0)then | |
$from + $range-size - 1 + $intervals-modulus | |
else | |
$from + $range-size - 1 | |
return | |
($from, $to) | |
} | |
, | |
if(not($oversize-last-interval) and $intervals-modulus gt 0)then | |
function() { | |
let $from := $range-size * $absolute-intervals + 1 | |
let $to := $from + $intervals-modulus - 1 | |
return | |
($from, $to) | |
} | |
else() | |
) | |
}; | |
(:~ | |
: Produces sequences of ranges ($from, $to) | |
: which span a $range-size | |
: all the way from 1 upto $range-to | |
: | |
: @param $range-to The top of the range to produce to | |
: @param $range-size The size of each range | |
: | |
: @return A sequence of functions. Each function itself | |
: returns a sequence ($from, $to) | |
:) | |
declare function ranges:range-intervals($range-to as xs:integer, $range-size as xs:integer) { | |
ranges:range-intervals(1, $range-to, $range-size, 0) | |
}; | |
(:~ | |
: Produces sequences of ranges ($from, $to) | |
: which span a $range-size | |
: all the way from 1 upto $range-to | |
: | |
: @param $range-to The top of the range to produce to | |
: @param $range-size The size of each range | |
: @param $oversize-threshold A percentage expressed as a decimal between | |
: 0 and 1. If greater than 0, then the last range may be upto | |
: $oversize-threshold bigger than preceding ranges. This allows you to | |
: create a fat last range rather than creating another range which contains | |
: perhaps just a few entries. | |
: | |
: @return A sequence of functions. Each function itself | |
: returns a sequence ($from, $to) | |
:) | |
declare function ranges:range-intervals($range-to as xs:integer, $range-size as xs:integer, $oversize-threshold as xs:decimal) { | |
ranges:range-intervals(1, $range-to, $range-size, $oversize-threshold) | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment