Skip to content

Instantly share code, notes, and snippets.

@adamretter
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamretter/a198305a2219e3766e92 to your computer and use it in GitHub Desktop.
Save adamretter/a198305a2219e3766e92 to your computer and use it in GitHub Desktop.
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