Map¶
A map is an unordered list of pair of elements, think of it like an associative array or an array<T, S> in the Psalm nomenclature. But with the added benefit that the keys can be of any type, even objects!
Named constructors¶
::of()¶
The first type is for the keys and the second one for the values. This order is the same for all the methods below.
Add values¶
->__invoke()¶
Augment the map with a new pair of elements. If the key already exist it will replace the value.
->put()¶
This is an alias for ->__invoke().
->merge()¶
Create a new map with all pairs from both maps. Pairs from the map in the argument will replace existing pairs from the original map.
$a = Map::of([1, 2], [3, 4]);
$b = Map::of([5, 6], [3, 7]);
$a->merge($b)->equals(
    Map::of(
        [1, 2],
        [5, 6],
        [3, 7],
    ),
); // true
Access values¶
->size()¶
This returns the number of elements in the map.
->count()¶
This is an alias for ->size(), but you can also use the PHP function \count if you prefer.
->get()¶
Return an instance of Maybe that may contain the value associated to the given key (if it exists).
->contains()¶
Check if the map contains a given key.
->keys()¶
Return a Set of all the keys of the map.
->values()¶
Return a Sequence of all the values of the map.
It returns a Sequence because it can contain duplicates, the order is not guaranteed as a map is not ordered.
->find()¶
This will return the first pair that matches the given predicate (remember that the map is not ordered).
use Innmind\Immutable\Pair;
Map::of([1, 2], [3, 4], [5, 6], [7, 8])->find(
    fn($key, $value) => ($key + $value) > 10,
); // Maybe::just(new Pair(5, 6))
->matches()¶
Check if all the pairs of the map matches the given predicate.
$isOdd = fn($i) => $i % 2 === 1;
Map::of([1, 2], [3, 4])->matches(fn($key) => $isOdd($key)); // true
Map::of([1, 2], [3, 4])->matches(fn($key, $value) => $isOdd($value)); // false
->any()¶
Check if at least one pair of the map matches the given predicate.
$isOdd = fn($i) => $i % 2 === 1;
Map::of([1, 2], [3, 4])->any(fn($key) => $isOdd($key)); // true
Map::of([1, 3], [3, 4])->any(fn($key, $value) => $isOdd($value)); // true
Map::of([1, 2], [3, 4])->any(fn($key, $value) => $isOdd($value)); // false
->empty()¶
Tells whether there is at least one pair or not.
Transform values¶
->map()¶
Create a new map of the same type with the exact same number of pairs but modified by the given function.
$urls = Map::of(
    ['example.com', 1],
    ['github.com', 1],
    ['news.ycombinator.com', 1],
    ['reddit.com', 1],
);
$incremented = $map->map(fn($key, $value) => $value + 1);
$incremented->equals(
    Map::of(
        ['example.com', 2]
        ['github.com', 2]
        ['news.ycombinator.com', 2]
        ['reddit.com', 2]
    ),
);
->flatMap()¶
This is similar to ->map() but instead of returning a new value it returns a new Map for each value, all maps are merged to form only one Map.
This is usefull to generate multiple pairs for each initial pair or to modify the keys.
$urls = Map::of(
    ['example.com', 1],
    ['github.com', 1],
    ['news.ycombinator.com', 1],
    ['reddit.com', 1],
);
$withScheme = $map->map(fn($key, $value) => Map::of(
    ["http://$key", $value],
    ["https://$key", $value],
));
$withScheme->equals(
    Map::of(
        ['http://example.com', 1],
        ['https://example.com', 1],
        ['http://github.com', 1],
        ['https://github.com', 1],
        ['http://news.ycombinator.com', 1],
        ['https://news.ycombinator.com', 1],
        ['http://reddit.com', 1],
        ['https://reddit.com', 1],
    ),
);
Filter values¶
->filter()¶
Removes the pairs from the map that don't match the given predicate.
$map = Map::of([1, 1], [3, 2]);
$map = $map->filter(fn($key, $value) => ($key + $value) % 2 === 0);
$map->equals(Map::of([1, 1]));
->exclude()¶
Removes the pairs from the map that match the given predicate.
$map = Map::of([1, 1], [3, 2]);
$map = $map->exclude(fn($key, $value) => ($key + $value) % 2 === 0);
$map->equals(Map::of([3, 2]));
->remove()¶
Remove the pair from the map with the given key.
Extract values¶
->reduce()¶
Iteratively compute a value for all the pairs in the map.
$map = Map::of([1, 2], [2, 3], [3, 3]);
$sum = $map->reduce(0, fn($sum, $key, $value) => $sum + $key + $value);
$sum; // 14
Misc.¶
->equals()¶
Check if two maps are identical.
$a = Map::of([1, 2], [3, 4]);
$b = Map::of([3, 4], [1, 2]);
$a->equals($b); // true
$a->equals(Map::of(); // false
->foreach()¶
Use this method to call a function for each pair of the map. Since this structure is immutable it returns a SideEffect object, as its name suggest it is the only place acceptable to create side effects.
$sideEffect = Map::of(['hello', 'world'])->foreach(
    function(string $key, string $value): void {
        echo "$key $value"; // will print "hello world"
    },
);
In itself the SideEffect object has no use except to avoid psalm complaining that the foreach method is not used.
->groupBy()¶
This will create multiples maps with elements regrouped under the same key computed by the given function.
$urls = Map::of(
    ['http://example.com', 1],
    ['http://example.com/foo', 1],
    ['https://example.com', 2],
    ['ftp://example.com', 4],
);
/** @var Innmind\Immutable\Map<string, Sequence<string>> */
$map = $urls->groupBy(fn(string $url, int $whatever): string => \parse_url($url)['scheme']);
$map
    ->get('http')
    ->match(
        static fn($group) => $group,
        static fn() => Map::of(),
    )
    ->equals(Map::of(
        ['http://example.com', 1],
        ['http://example.com/foo', 1]
    )); // true
$map
    ->get('https')
    ->match(
        static fn($group) => $group,
        static fn() => Map::of(),
    )
    ->equals(Map::of(['https://example.com', 2])); // true
$map
    ->get('ftp')
    ->match(
        static fn($group) => $group,
        static fn() => Map::of(),
    )
    ->equals(Map::of(['ftp://example.com', 4])); // true
->partition()¶
This method is similar to ->groupBy() method but the map keys are always booleans. The difference is that here the 2 keys are always present whereas with ->groupBy() it will depend on the original map.
$map = Map::of([1, 2], [2, 3], [3, 3]);
/** @var Map<bool, Map<int, int>> */
$map = $map->partition(fn($key, $value) => ($key + $value) % 2 === 0);
$map
    ->get(true)
    ->match(
        static fn($partition) => $partition,
        static fn() => Map::of(),
    )
    ->equals(Map::of([3, 3])); // true
$map
    ->get(false)
    ->match(
        static fn($partition) => $partition,
        static fn() => Map::of(),
    )
    ->equals(Map::of([1, 2], [2, 3])); // true
->clear()¶
Return an empty new map of the same type. Useful to avoid to respecify the templates types of the map in a new docblock annotation.
->toSequence()¶
Returns an unsorted Sequence with all value pairs.