Menu

Reference / Manticore\Ds

Map

finalclass
final class Map<K, V> implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonSerializable

An insertion-ordered hash map from keys of any hashable kind to values.

Unlike a PHP array, a Map key may be an int, a string or an object, and the kinds never merge: 1 and '1' are two different keys, and two objects are two keys unless they are the same instance. Any other key type (float, bool, null, array) throws a TypeError.

Iteration order is insertion order. Overwriting an existing key keeps its position; removing a key and setting it again moves it to the end. get(), set(), has() and remove() run in O(1) on average.

A Map is an object: assigning it copies the handle, not the contents. Use clone for an independent (shallow) copy. It implements ArrayAccess ($map[$k], isset($map[$k]), unset($map[$k])), Countable, IteratorAggregate (foreach ($map as $k => $v)) and JsonSerializable (encoded as a JSON object).

Changing the map while it is being iterated is not supported. Updating the value of a key that is already present is safe, and so is removing keys (the loop skips them). Adding a new key or clear() makes the running loop throw a RuntimeException ("Map modified during iteration") after the current step.

$ages = new Map();
$ages->set('ann', 31);
echo $ages['ann'];   // 31

Example

use Manticore\Ds\Map;

$stock = new Map();
$stock->set('apple', 3);
$stock['pear'] = 5;
$stock->set('apple', 4);        // overwrite: keeps its position

echo count($stock), "\n";       // 2
echo $stock['apple'], "\n";     // 4
echo $stock->get('plum', 0), "\n";   // 0: the default for a missing key
var_dump($stock->has('pear'));

try {
    $stock->get('plum');
} catch (OutOfBoundsException $e) {
    echo get_class($e), ': ', $e->getMessage(), "\n";
}

// Keys keep their type: 1 and '1' are different keys.
$stock->set(1, 'int');
$stock->set('1', 'string');

foreach ($stock as $key => $value) {
    echo var_export($key, true), ' => ', $value, "\n";
}

$stock->remove('apple');
echo json_encode($stock->filter(fn($v, $k) => is_int($v))), "\n";

Output

2
4
0
bool(true)
OutOfBoundsException: Key not found
'apple' => 4
'pear' => 5
1 => int
'1' => string
{"pear":5}

See also: Set, Vec

Methods

__construct()Creates an empty map.
__clone()Makes the clone an independent map with the same entries (values are copied shallowly).
get()Returns the value stored under $key.
set()Stores $value under $key, replacing any previous value.
has()Tells whether $key is present, whatever its value (a stored null counts).
remove()Removes $key and returns the value it held.
count()Returns the number of entries.
isEmpty()Tells whether the map has no entries.
clear()Removes every entry.
toArray()Copies the entries into a PHP array, in iteration order.
getIterator()Iterates the entries in insertion order, yielding key => value.
offsetExists()Array-access form of {@see has()}: isset($map[$offset]).
offsetGet()Array-access form of {@see get()}: $map[$offset].
offsetSet()Array-access form of {@see set()}: $map[$offset] = $value.
offsetUnset()Removes $offset if present: unset($map[$offset]).
jsonSerialize()Encodes as a JSON object (an empty map is {}).
keys()Returns the keys, in iteration order.
values()Returns the values, in iteration order.
each()Calls $f($value, $key) for every entry, in order.
map()Builds a new map with the same keys and $f($value, $key) as values.
filter()Builds a new map with the entries for which $f($value, $key) is truthy.
reduce()Folds the entries into one value: $carry = $f($carry, $value, $key).
any()Tells whether $f($value, $key) is truthy for at least one entry (stops at the first).
all()Tells whether $f($value, $key) is truthy for every entry (stops at the first miss).
find()Returns the first value for which $f($value, $key) is truthy.

__construct()#source

function __construct()

Creates an empty map.

__clone()#source

function __clone()

Makes the clone an independent map with the same entries (values are copied shallowly).

get()#source

function get(mixed $key, mixed $default = null): mixed

Returns the value stored under $key.

When the key is absent the call returns $default if one was passed (even an explicit null), and throws OutOfBoundsException if not. $map[$key] is the same as get($key) without a default.

Parameters

$key K
the key to look up
$default mixed = null
returned when $key is absent; omit it to get an exception instead

Returns

V — the stored value

Throws

\OutOfBoundsException
when the key is absent and no default was passed
\TypeError
when $key is not an int, a string or an object

set()#source

function set(mixed $key, mixed $value): void

Stores $value under $key, replacing any previous value.

A new key goes to the end of the iteration order; an existing key keeps its position. $map[$key] = $value is the same call.

Parameters

$key K
the key
$value V
the value to store

Throws

\TypeError
when $key is not an int, a string or an object

has()#source

function has(mixed $key): bool

Tells whether $key is present, whatever its value (a stored null counts).

isset($map[$key]) calls this method.

Parameters

$key K
the key to look up

Returns

bool — true when the key is present

Throws

\TypeError
when $key is not an int, a string or an object

remove()#source

function remove(mixed $key): mixed

Removes $key and returns the value it held.

unset($map[$key]) does the same but ignores an absent key.

Parameters

$key K
the key to remove

Returns

V — the removed value

Throws

\OutOfBoundsException
when the key is absent
\TypeError
when $key is not an int, a string or an object

count()#source

function count(): int

Returns the number of entries.

Returns

int — the entry count

isEmpty()#source

function isEmpty(): bool

Tells whether the map has no entries.

Returns

bool — true when empty

clear()#source

function clear(): void

Removes every entry.

toArray()#source

function toArray(): array

Copies the entries into a PHP array, in iteration order.

Only maps whose keys can be array keys convert: an object key throws TypeError, and two keys that PHP arrays would merge (1 and '1') throw ValueError.

Returns

array<int|string, V> — the entries as a PHP array

Throws

\TypeError
when a key is an object
\ValueError
when two keys collide in a PHP array

getIterator()#source

function getIterator(): \Generator

Iterates the entries in insertion order, yielding key => value.

Returns

\Generator — a generator over the entries

Throws

\RuntimeException
when the map is changed in a way the running loop cannot follow

offsetExists()#source

function offsetExists(mixed $offset): bool

Array-access form of {@see has()}: isset($map[$offset]).

Parameters

$offset mixed
the key

Returns

bool — true when the key is present

offsetGet()#source

function offsetGet(mixed $offset): mixed

Array-access form of {@see get()}: $map[$offset].

Parameters

$offset mixed
the key

Returns

mixed — the stored value

Throws

\OutOfBoundsException
when the key is absent

offsetSet()#source

function offsetSet(mixed $offset, mixed $value): void

Array-access form of {@see set()}: $map[$offset] = $value.

Parameters

$offset mixed
the key
$value mixed
the value to store

Throws

\Error
on $map[] = $value: a map has no append, use set()

offsetUnset()#source

function offsetUnset(mixed $offset): void

Removes $offset if present: unset($map[$offset]). An absent key is ignored.

Parameters

$offset mixed
the key

Throws

\TypeError
when $offset is not an int, a string or an object

jsonSerialize()#source

function jsonSerialize(): mixed

Encodes as a JSON object (an empty map is {}).

Uses {@see toArray()}, so the same key restrictions apply.

Returns

mixed — an object ready for json_encode

Throws

\TypeError
when a key is an object
\ValueError
when two keys collide in a PHP array

keys()#source

function keys(): Vec

Returns the keys, in iteration order.

Returns

Vec<K> — a new vector of the keys

values()#source

function values(): Vec

Returns the values, in iteration order.

Returns

Vec<V> — a new vector of the values

each()#source

function each(callable $f): void

Calls $f($value, $key) for every entry, in order.

Parameters

$f callable(V, K): void
the callback

map()#source

function map(callable $f): Map

Builds a new map with the same keys and $f($value, $key) as values.

Parameters

$f callable(V, K): U
maps a value (and its key) to the new value

Returns

Map<K, U> — a new map; this one is unchanged

filter()#source

function filter(callable $f): Map

Builds a new map with the entries for which $f($value, $key) is truthy.

Parameters

$f callable(V, K): bool
the predicate

Returns

Map<K, V> — a new map; this one is unchanged

reduce()#source

function reduce(callable $f, mixed $initial): mixed

Folds the entries into one value: $carry = $f($carry, $value, $key).

Parameters

$f callable(R, V, K): R
combines the carry with the next entry
$initial R
the starting carry, also the result for an empty map

Returns

R — the final carry

any()#source

function any(callable $f): bool

Tells whether $f($value, $key) is truthy for at least one entry (stops at the first).

Parameters

$f callable(V, K): bool
the predicate

Returns

bool — false for an empty map

all()#source

function all(callable $f): bool

Tells whether $f($value, $key) is truthy for every entry (stops at the first miss).

Parameters

$f callable(V, K): bool
the predicate

Returns

bool — true for an empty map

find()#source

function find(callable $f): mixed

Returns the first value for which $f($value, $key) is truthy.

null means "none matched" but is also a valid stored value; use {@see any()} when the map can hold null.

Parameters

$f callable(V, K): bool
the predicate

Returns

?V — the first matching value, or null

View source