-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from cmatosbc/adding
Enhancements.
- Loading branch information
Showing
9 changed files
with
1,022 additions
and
720 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
<?php | ||
|
||
namespace Daedalus; | ||
|
||
use InvalidArgumentException; | ||
use Countable; | ||
|
||
/** | ||
* A map implementation that allows multiple values to be associated with a single key. | ||
*/ | ||
class MultiMap implements Countable | ||
{ | ||
private array $map = []; | ||
private bool $allowDuplicates; | ||
|
||
/** | ||
* Create a new MultiMap instance | ||
* | ||
* @param bool $allowDuplicates Whether to allow duplicate values for the same key | ||
*/ | ||
public function __construct(bool $allowDuplicates = true) | ||
{ | ||
$this->allowDuplicates = $allowDuplicates; | ||
} | ||
|
||
/** | ||
* Add a value to the collection of values associated with a key | ||
* | ||
* @param mixed $key The key | ||
* @param mixed $value The value to add | ||
* @return bool True if the value was added, false if it was a duplicate and duplicates are not allowed | ||
*/ | ||
public function put($key, $value): bool | ||
{ | ||
if (!isset($this->map[$key])) { | ||
$this->map[$key] = []; | ||
} | ||
|
||
if (!$this->allowDuplicates && in_array($value, $this->map[$key], true)) { | ||
return false; | ||
} | ||
|
||
$this->map[$key][] = $value; | ||
return true; | ||
} | ||
|
||
/** | ||
* Get all values associated with a key | ||
* | ||
* @param mixed $key The key to look up | ||
* @return array Array of values associated with the key | ||
*/ | ||
public function get($key): array | ||
{ | ||
return $this->map[$key] ?? []; | ||
} | ||
|
||
/** | ||
* Remove a specific value from a key's collection | ||
* | ||
* @param mixed $key The key | ||
* @param mixed $value The value to remove | ||
* @return bool True if the value was removed, false if it wasn't found | ||
*/ | ||
public function removeValue($key, $value): bool | ||
{ | ||
if (!isset($this->map[$key])) { | ||
return false; | ||
} | ||
|
||
$index = array_search($value, $this->map[$key], true); | ||
if ($index === false) { | ||
return false; | ||
} | ||
|
||
array_splice($this->map[$key], $index, 1); | ||
if (empty($this->map[$key])) { | ||
unset($this->map[$key]); | ||
} | ||
return true; | ||
} | ||
|
||
/** | ||
* Remove all values associated with a key | ||
* | ||
* @param mixed $key The key to remove | ||
* @return array The removed values | ||
*/ | ||
public function removeAll($key): array | ||
{ | ||
$values = $this->get($key); | ||
unset($this->map[$key]); | ||
return $values; | ||
} | ||
|
||
/** | ||
* Get all keys that have at least one value | ||
* | ||
* @return array | ||
*/ | ||
public function keys(): array | ||
{ | ||
return array_keys($this->map); | ||
} | ||
|
||
/** | ||
* Get all values in the multimap | ||
* | ||
* @return array | ||
*/ | ||
public function values(): array | ||
{ | ||
return array_merge(...array_values($this->map)); | ||
} | ||
|
||
/** | ||
* Check if the multimap contains a key | ||
* | ||
* @param mixed $key The key to check | ||
* @return bool | ||
*/ | ||
public function containsKey($key): bool | ||
{ | ||
return isset($this->map[$key]); | ||
} | ||
|
||
/** | ||
* Check if the multimap contains a value for any key | ||
* | ||
* @param mixed $value The value to check | ||
* @return bool | ||
*/ | ||
public function containsValue($value): bool | ||
{ | ||
foreach ($this->map as $values) { | ||
if (in_array($value, $values, true)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* Get the total number of values across all keys | ||
* | ||
* @return int | ||
*/ | ||
public function count(): int | ||
{ | ||
return array_sum(array_map('count', $this->map)); | ||
} | ||
|
||
/** | ||
* Get the number of keys in the multimap | ||
* | ||
* @return int | ||
*/ | ||
public function keyCount(): int | ||
{ | ||
return count($this->map); | ||
} | ||
|
||
/** | ||
* Clear all entries from the multimap | ||
* | ||
* @return void | ||
*/ | ||
public function clear(): void | ||
{ | ||
$this->map = []; | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
<?php | ||
|
||
namespace Daedalus; | ||
|
||
use InvalidArgumentException; | ||
|
||
/** | ||
* A map implementation that keeps its keys in sorted order. | ||
* Keys must be comparable (strings, numbers, or objects implementing Comparable). | ||
*/ | ||
class SortedMap | ||
{ | ||
private array $entries = []; | ||
private $comparator; | ||
|
||
/** | ||
* Create a new SortedMap instance | ||
* | ||
* @param callable|null $comparator Optional custom comparison function | ||
*/ | ||
public function __construct(?callable $comparator = null) | ||
{ | ||
$this->comparator = $comparator ?? fn($a, $b) => $a <=> $b; | ||
} | ||
|
||
/** | ||
* Put a key-value pair into the map | ||
* | ||
* @param mixed $key The key | ||
* @param mixed $value The value | ||
* @return void | ||
*/ | ||
public function put($key, $value): void | ||
{ | ||
$this->entries[$key] = $value; | ||
$this->sort(); | ||
} | ||
|
||
/** | ||
* Get a value by key | ||
* | ||
* @param mixed $key The key to look up | ||
* @return mixed|null The value, or null if not found | ||
*/ | ||
public function get($key) | ||
{ | ||
return $this->entries[$key] ?? null; | ||
} | ||
|
||
/** | ||
* Remove a key-value pair from the map | ||
* | ||
* @param mixed $key The key to remove | ||
* @return void | ||
*/ | ||
public function remove($key): void | ||
{ | ||
unset($this->entries[$key]); | ||
} | ||
|
||
/** | ||
* Get all keys in sorted order | ||
* | ||
* @return array | ||
*/ | ||
public function keys(): array | ||
{ | ||
return array_keys($this->entries); | ||
} | ||
|
||
/** | ||
* Get all values in order corresponding to sorted keys | ||
* | ||
* @return array | ||
*/ | ||
public function values(): array | ||
{ | ||
return array_values($this->entries); | ||
} | ||
|
||
/** | ||
* Get the first key in the sorted map | ||
* | ||
* @return mixed|null | ||
*/ | ||
public function firstKey() | ||
{ | ||
if (empty($this->entries)) { | ||
return null; | ||
} | ||
$keys = $this->keys(); | ||
return reset($keys); | ||
} | ||
|
||
/** | ||
* Get the last key in the sorted map | ||
* | ||
* @return mixed|null | ||
*/ | ||
public function lastKey() | ||
{ | ||
if (empty($this->entries)) { | ||
return null; | ||
} | ||
$keys = $this->keys(); | ||
return end($keys); | ||
} | ||
|
||
/** | ||
* Check if the map contains a key | ||
* | ||
* @param mixed $key The key to check | ||
* @return bool | ||
*/ | ||
public function containsKey($key): bool | ||
{ | ||
return array_key_exists($key, $this->entries); | ||
} | ||
|
||
/** | ||
* Get the number of entries in the map | ||
* | ||
* @return int | ||
*/ | ||
public function count(): int | ||
{ | ||
return count($this->entries); | ||
} | ||
|
||
/** | ||
* Clear all entries from the map | ||
* | ||
* @return void | ||
*/ | ||
public function clear(): void | ||
{ | ||
$this->entries = []; | ||
} | ||
|
||
/** | ||
* Sort the internal entries array using the comparator | ||
*/ | ||
private function sort(): void | ||
{ | ||
uksort($this->entries, $this->comparator); | ||
} | ||
} |
Oops, something went wrong.