Java has a nifty class named NavigableMap
. It abstracts away some of the logic for mapping ranges to values. Java is reknowned for it’s ridiculously large library of collections.
Here’s a PHP implementation of some of its functionality.
class NavigableMap {
private $data = array();
private function checkKeyNumeric($key) {
if (!is_numeric($key)) {
throw new Exception("keys must be numeric. Given $key");
}
}
public function put($key, $value) {
$this->checkKeyNumeric($key);
$this->data[$key] = $value;
ksort($this->data);
}
public function firstEntry() {
return key($this->data);
}
public function lastEntry() {
$end = key($this->data);
reset($this->data);
return $end;
}
public function floorEntry($point) {
return $this->data[$this->floorKey($point)];
}
public function floorKey($point) {
$this->checkKeyNumeric($point);
$lowest = $this->firstEntry();
if ($lowest > $point) {
throw new OutOfBoundsException("no point exists " .
"below $point. Lowest map entry is $lowest");
}
foreach($this->data as $key => $value) {
if ($key > $point) {
return $previous_key;
}
$previous_key = $key;
}
return $previous_key;
}
public function ceilingEntry($point) {
return $this->data[$this->ceilingKey($point)];
}
public function ceilingKey($point) {
$this->checkKeyNumeric($point);
$highest = $this->lastEntry();
if ($highest < $point) {
throw new OutOfBoundsException("no point exists " .
"above $point. Highest map entry is $highest");
}
$keys = array_reverse(array_keys($this->data));
foreach($keys as $key) {
if ($key < $point) {
return $previous_key;
}
$previous_key = $key;
}
return $previous_key;
}
}