range_map

A RangeMap maps ranges to values. Keys must be hashable and comparable to all other keys (but not necessarily the same type). Each range a:b maps all values a <= x < b so it includes a but not b.

Examples

>>> from collections_extended import RangeMap
>>> from datetime import date
>>> us_presidents = RangeMap()
>>> us_presidents[date(1993, 1, 20):date(2001, 1, 20)] = 'Bill Clinton'
>>> us_presidents[date(2001, 1, 20):date(2009, 1, 20)] = 'George W. Bush'
>>> us_presidents[date(2009, 1, 20):] = 'Barack Obama'
>>> us_presidents[date(2001, 1, 19)]
'Bill Clinton'
>>> us_presidents[date(2001, 1, 20)]
'George W. Bush'
>>> us_presidents[date(2021, 3, 1)]
'Barack Obama'
>>> us_presidents[date(2017, 1, 20):] = 'Someone New'
>>> us_presidents[date(2021, 3, 1)]
'Someone New'

Creating RangeMaps

RangeMaps can be passed a mapping upon creation. Each key, value pair is interpreted as the start of a range and the mapped value. The end of the range is the next largest key in the mapping.

RangeMaps can also be created from RangeMap.from_iterable(iterable) where the iterable’s elements are tuples (start, stop, value). A start or stop key of None denotes an open range, ie. a start key of None is analgous to -infinity if the keys are all numbers.

Quirks

Python 2 vs 3

Slice notation is not implemented for get, set and delete in python 2 and raises a SyntaxError when used. This is because Python 2 assumes slices are integers and replaces open slices with 0 and maxint. Instead use RangeMap.set, RangeMap.delete and RangeMap.get_range.

PyPy

pypy (not pypy3) cannot accept non-ints in __getitem__ so RangeMap[1.5:3] doesn’t work.

Implementation

RangeMaps are backed by lists of the keys, so it’s only fast to add/remove the greatest values in the range (the end of the list).

API

class collections_extended.RangeMap(iterable=None, default_value=<not_set>)[source]

Map ranges of orderable elements to values.

__init__(iterable=None, default_value=<not_set>)[source]

Create a RangeMap.

A mapping or other iterable can be passed to initialize the RangeMap. If mapping is passed, it is interpreted as a mapping from range start indices to values. If an iterable is passed, each element will define a range in the RangeMap and should be formatted (start, stop, value).

default_value is a an optional keyword argument that will initialize the entire RangeMap to that value. Any missing ranges will be mapped to that value. However, if ranges are subsequently deleted they will be removed and not mapped to the default_value.

Parameters:
  • iterable – A Mapping or an Iterable to initialize from.
  • default_value – If passed, the return value for all keys less than the least key in mapping or missing ranges in iterable. If no mapping or iterable, the return value for all keys.
class collections_extended.MappedRange(start, stop, value)[source]

Represents a subrange of a RangeMap.

This is a glorified namedtuple.

__init__(start, stop, value)[source]

Create a mapped range.

Parameters:
  • start – The start of the range, inclusive.
  • stop – The end of the range, exclusive.
  • value – The mapped value.