00001 <?php
00002
00010 class spunQ_Map implements spunQ_IMap {
00011
00016 private static $emptyMap;
00017
00022 public static function emptyMap() {
00023 if (self::$emptyMap === NULL) {
00024 self::$emptyMap = new spunQ_ReadonlyMap();
00025 }
00026 return self::$emptyMap;
00027 }
00028
00033 private $keys = array();
00034
00039 private $values = array();
00040
00045 private $iteratorIndex = 0;
00046
00052 public function __construct($collection = array()) {
00053 if ($collection instanceof spunQ_Map) {
00054 $this->keys = $collection->keys;
00055 $this->values = $collection->values;
00056 } elseif (is_array($collection)) {
00057 $this->keys = array_keys($collection);
00058 $this->values = array_values($collection);
00059 }
00060 return NULL;
00061 }
00062
00066 public function setKeysAndValues($keys, $values) {
00067 $this->keys = $keys;
00068 $this->values = $values;
00069 return $this;
00070 }
00071
00075 public function getAnyKey() {
00076 if (count($this->keys) === 0) {
00077 return NULL;
00078 }
00079 return reset($this->keys);
00080 }
00081
00085 public function getRandomKey() {
00086 $count = count($this->keys);
00087 if ($count === 0) {
00088 return NULL;
00089 }
00090 return $this->keys[rand(0, $count - 1)];
00091 }
00092
00096 public function getKeys() {
00097 return $this->keys;
00098 }
00099
00103 public function getValues() {
00104 return $this->values;
00105 }
00106
00110 public function add($key, $value) {
00111 $index = array_search($key, $this->keys, true);
00112 if ($index !== false) {
00113 $this->values[$index] = $value;
00114 } else {
00115 $this->keys[] = $key;
00116 $this->values[] = $value;
00117 }
00118 return $this;
00119 }
00120
00124 public function remove($key) {
00125 $index = array_search($key, $this->keys, true);
00126 if ($index !== false) {
00127 $this->keys[$index] = end($this->keys);
00128 $this->values[$index] = end($this->values);
00129 array_pop($this->keys);
00130 array_pop($this->values);
00131 }
00132 return $this;
00133 }
00134
00138 public function removeMultiple(array $keys) {
00139 # We could have been using array_intersect() here, but nooo, PHP does
00140 # not have an array_intersect() version that can compare strictly
00141 # (i.e. using the type-safe comparison ===)
00142 foreach ($keys as $key) {
00143 $this->remove($key);
00144 }
00145 return $this;
00146 }
00147
00151 public function extract($keys) {
00152 # see removeMultiple()
00153 $result = new spunQ_Map();
00154 $count = count($this->keys);
00155 for ($i = 0; $i < $count; $i++) {
00156 if (in_array($this->keys[$i], $keys, true)) {
00157 $result->add($this->keys[$i], $this->values[$i]);
00158 }
00159 }
00160 return $result;
00161 }
00162
00166 public function intersect(spunQ_Map $otherMap) {
00167 return $this->extract($otherMap->keys);
00168 }
00169
00173 public function equals(spunQ_Map $otherMap) {
00174 return $this->keys === $otherMap->keys
00175 && $this->values === $otherMap->values;
00176 }
00177
00181 public function isEmpty() {
00182 return count($this->keys) === 0;
00183 }
00184
00188 public function &get($key) {
00189 # XXX: Update getByKey() and getByValue() if you change this code.
00190 $index = array_search($key, $this->keys, true);
00191 if ($index === false) {
00192 $null = NULL;
00193 return $null;
00194 }
00195 return $this->values[$index];
00196 }
00197
00201 public function &getByKey($key) {
00202 # XXX: Update getByValue() and get() if you change this code.
00203 $index = array_search($key, $this->keys, true);
00204 if ($index === false) {
00205 $null = NULL;
00206 return $null;
00207 }
00208 return $this->values[$index];
00209 }
00210
00214 public function &getByValue($value) {
00215 # XXX: Update getByKey() and get() if you change this code.
00216 $index = array_search($value, $this->values, true);
00217 if ($index === false) {
00218 $null = NULL;
00219 return $null;
00220 }
00221 return $this->keys[$index];
00222 }
00223
00227 public function getAllKeysByValue($value) {
00228 $keys = array_keys($this->values, $value, true);
00229 if (!isset($keys[0])) {
00230 return array();
00231 }
00232 return array_values(array_intersect_key($this->keys, array_combine($keys, array_fill(1, count($keys), NULL))));
00233 }
00234
00238 public function getPairs() {
00239 $pairs = array();
00240 $count = count($this->keys);
00241 for ($i = 0; $i < $count; $i++) {
00242 $pairs[] = array($this->keys[$i], $this->values[$i]);
00243 }
00244 return $pairs;
00245 }
00246
00250 public function getSize() {
00251 return count($this->keys);
00252 }
00253
00257 public function toAssociativeArray() {
00258 if (count($this->keys) === 0) {
00259 return array();
00260 }
00261 return array_combine($this->keys, $this->values);
00262 }
00263
00267 public function keyExists($key) {
00268 return in_array($key, $this->keys, true);
00269 }
00270
00274 public function valueExists($value) {
00275 return in_array($value, $this->values, true);
00276 }
00277
00281 public function copyFrom(spunQ_Map $otherMap) {
00282 foreach ($otherMap->getKeys() as $key) {
00283 $this->add($key, $otherMap->get($key));
00284 }
00285 return $this;
00286 }
00287
00291 public function clear() {
00292 $this->keys = array();
00293 $this->values = array();
00294 return $this;
00295 }
00296
00302 public function rewind() {
00303 $this->iteratorIndex = 0;
00304 return NULL;
00305 }
00306
00312 public function valid() {
00313 return $this->iteratorIndex < count($this->keys);
00314 }
00315
00321 public function current() {
00322 if ($this->iteratorIndex >= count($this->keys)) {
00323 return NULL;
00324 }
00325 return $this->values[$this->iteratorIndex];
00326 }
00327
00333 public function key() {
00334 if ($this->iteratorIndex >= count($this->keys)) {
00335 return NULL;
00336 }
00337 return $this->keys[$this->iteratorIndex];
00338 }
00339
00345 public function next() {
00346 $this->iteratorIndex++;
00347 return NULL;
00348 }
00349
00354 public function offsetExists($key) {
00355 return $this->keyExists($key);
00356 }
00357
00362 public function offsetGet($key) {
00363 return $this->getByKey($key);
00364 }
00365
00370 public function offsetSet($key, $val) {
00371 return $this->add($key, $val);
00372 }
00373
00378 public function offsetUnset($key) {
00379 return $this->remove($key);
00380 }
00381
00382 }
00383