Repository files navigation

Micoli\Multitude

A collection library for PHP.

Build StatusCoverage StatusLatest Stable VersionTotal DownloadsLatest Unstable VersionLicensePHP Version Require

Two types of collections are available:

  • Sets (MutableSet and ImmutableSet), are sequences of unique values. Values can be of any types.
  • Map (MutableMap and ImmutableMap), is a sequential collection of key-value pairs. Keys can be any type, but must be unique. Values can be of any types.

In both ImmutableSet and ImmutableMap, if a method alter the content af the inner values, a new instance is returned of the same type. Oppositely, in MutableSet and MutableMap, same methods are altering the inner values.

Methods are the most possible fluent.

Thanks to https://github.com/BenMorel for the main ideas used in that library, this is a complete rewrite of it's initial version.

Installation

This library is installable via Composer:

composer require micoli/multitude

Requirements

This library requires PHP 8.0 or later.

Project status

While this library is still under development, it is still in early development status. It follows semver version tagging.

Quick start

Constructor are only statics:

  • new MutableSet(['a','b','c'])
  • new MutableMap([2=>'a',3=>'b',4=>'c'])
  • new MutableMap([[2,'a'],['2','aa'],[3,'b'],['3','bb'],[4,'c'])

You can use fromTuples constructor if you need a strong typing for keys of your map, e.g. '2' key is different of 2.

Methods that accept a bool $throw parameter will trigger an exception if $throw == true or fails silently if $throw == false.

Example with an associative array

publicfunctiontestItShouldFullyWorkWithAssociativeArray(): void
{
/** @var ImmutableMap<string, array{value:int,tags:list<string>}> $map */$map = newImmutableMap([
['library', ['value' => 10, 'tags' => ['tag1']]],
['projects', ['value' => 5, 'tags' => ['tag2']]],
['gist', ['value' => 7, 'tags' => ['tag1', 'tag2']]],
['repository', ['value' => 7, 'tags' => ['tag3']]],
]);
$totalSum = $map
->filter(fn (array$project, mixed$category): bool => array_search('tag1', $project['tags']) !== false)
->reduce(fn (int$sum, mixed$project, mixed$category): int => $sum + $project['value'], 0);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
}

Example with an immutable map fully typed

File: Project.php

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
class Project
{
publicfunction__construct(
publicreadonlyint$value,
publicreadonlyTags$tags,
) {
}
}

File: Tags

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Set\ImmutableSet;
/** * @extends ImmutableSet<string> */class Tags extends ImmutableSet
{
}

File: Projects

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Map\ImmutableMap;
/** * @extends ImmutableMap<string, Project> */class Projects extends ImmutableMap
{
/** * Add or replace a value in the map */publicfunctionimprovedSet(string$newKey, Project$newValue): static
{
// do specific stuff, like logging or therreturn$this->set($newKey, $newValue);
}
}
publicfunctiontestItShouldFullyWorkWithObjects(): void
{
$map = newProjects([
['library', newProject(10, newTags(['tag1']))],
['projects', newProject(5, newTags(['tag2']))],
['gist', newProject(7, newTags(['tag1', 'tag2']))],
['repository', newProject(7, newTags(['tag3']))],
]);
$totalSum = $map
->filter(fn (Project$project, mixed$category): bool => $project->tags->hasValue('tag1'))
->reduce(fn (int$sum, Project$project, mixed$category): int => $sum + $project->value, 0);
self::assertInstanceOf(
Projects::class,
$map->filter(fn (Project$project, mixed$category): bool => true),
);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
$newMap = $map->improvedSet('NewType', newProject(10, newTags(['tag4'])));
self::assertCount(5, $newMap);
}

Available verbs

Verb parity

ImmutableMapMutableMapImmutableSetMutableSet
__construct[x][x][x][x]
append[x][x]
apply[x][x][x][x]
count[x][x][x][x]
filter[x][x][x][x]
first[x][x][x][x]
forEach[x][x][x][x]
fromIterable[x][x]
get[x][x][x][x]
getIterator[x][x][x][x]
getTuples[x][x]
hasIndex[x][x]
hasKey[x][x]
hasValue[x][x][x][x]
indexDiff[x][x]
indexIntersect[x][x]
isEmpty[x][x][x][x]
keyDiff[x][x]
keyIntersect[x][x]
keys[x][x][x][x]
ImmutableMapMutableMapImmutableSetMutableSet
last[x][x][x][x]
map[x][x][x][x]
offsetExists[x][x]
offsetGet[x][x]
offsetSet[x][x]
offsetUnset[x][x]
reduce[x][x][x][x]
remove[x][x]
removeKey[x][x]
removeValue[x][x]
set[x][x]
slice[x][x][x][x]
sort[x][x][x][x]
toArray[x][x][x][x]
toImmutable[x][x]
toMutable[x][x]
valueDiff[x][x][x][x]
valueIntersect[x][x][x][x]
values[x][x][x][x]

AbstractSet

AbstractMap

AbstractSet

AbstractSet::__construct

public function __construct(iterable $values = [])

AbstractSet::append

public function append(mixed $newValue, bool $throw = true): static

Append a value at the end of the set

AbstractSet::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractSet::count

public function count(): int

return the number of items in the set

AbstractSet::filter

public function filter(callable $callable): static

Filter the set using a callback function

AbstractSet::first

public function first(bool $throw = true): mixed

Return the first value in the set

AbstractSet::forEach

public function forEach(callable $callable): static

Apply a callback on set values

Callback receive $value and $index

AbstractSet::get

public function get(int $index, mixed $defaultValue = null): mixed

Return a value in the set by index

AbstractSet::getIterator

public function getIterator(): Traversable

Return an iterator for values

AbstractSet::hasIndex

public function hasIndex(int $index): bool

Return if a set contains an index

AbstractSet::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a set contains a value

AbstractSet::indexDiff

public function indexDiff(AbstractSet $compared): static

Return a set of all items where keys are not in argument set

AbstractSet::indexIntersect

public function indexIntersect(AbstractSet $compared): static

Return a map of all items where keys are in arguments map

AbstractSet::isEmpty

public function isEmpty(): bool

Return if a set is empty

AbstractSet::keys

public function keys(): Generator

Return an iterator of keys

AbstractSet::last

public function last(bool $throw = true): mixed

Return the latest value in the set

AbstractSet::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

Callback receive $value and $index

AbstractSet::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Set to a single value using a callback function

Callback receive $accumulator,$value and $index

AbstractSet::remove

public function remove(mixed $searchedValue, bool $throw = true): static

Remove a value in the set

AbstractSet::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the set

AbstractSet::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable (TValue, TValue, int, int): int

and must return -1,0,1 as spaceship operator

AbstractSet::toArray

public function toArray(): array

Return an array representing the values

AbstractSet::valueDiff

public function valueDiff(AbstractSet $compared): static

Return a Set of all items where values are not in argument set

AbstractSet::valueIntersect

public function valueIntersect(AbstractSet $compared): static

Return a set of all items where values are in argument set

AbstractSet::values

public function values(): Generator

Return an iterator of values

AbstractMap

AbstractMap::__construct

public function __construct(array $tuples = [])

AbstractMap::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractMap::count

public function count(): int

Return the number of items in the map

AbstractMap::filter

public function filter(callable $callable): static

Filter the map using a callback function

AbstractMap::first

public function first(bool $throw = true): mixed

Return the first value in the map

AbstractMap::forEach

public function forEach(callable $callable): static

Apply a callback on set values

AbstractMap::fromIterable

public static function fromIterable(iterable $values): static

Return a new instance from an array.

AbstractMap::get

public function get(mixed $searchedKey, mixed $defaultValue = null): mixed

Return a value in the map by index

AbstractMap::getIterator

public function getIterator(): Traversable

Return an iterator for values by keys

AbstractMap::getTuples

public function getTuples(): array

AbstractMap::hasKey

public function hasKey(mixed $searchedKey): bool

Return if a map contains a specific key

AbstractMap::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a map contains a specific value

AbstractMap::isEmpty

public function isEmpty(): bool

Return if a map is empty

AbstractMap::keyDiff

public function keyDiff(AbstractMap $compared): static

Return a map of all items where keys are not in argument map

AbstractMap::keyIntersect

public function keyIntersect(AbstractMap $compared): static

Return a map of all items where keys are in arguments map

AbstractMap::keys

public function keys(): Generator

Return an iterator of keys

AbstractMap::last

public function last(bool $throw = true): mixed

Return the latest value in the map

AbstractMap::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

AbstractMap::offsetExists

public function offsetExists(mixed $offset): bool

AbstractMap::offsetGet

public function offsetGet(mixed $offset): mixed

AbstractMap::offsetSet

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

AbstractMap::offsetUnset

public function offsetUnset(mixed $offset): void

AbstractMap::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Map to a single value using a callback function

Callback receive $accumulator,$value and $key

AbstractMap::removeKey

public function removeKey(mixed $searchedKey): static

Remove a value in the map by key

AbstractMap::removeValue

public function removeValue(mixed $searchedValue): static

Remove a value in the map by value

AbstractMap::set

public function set(mixed $newKey, mixed $newValue): static

Add or replace a value in the map

AbstractMap::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the map

AbstractMap::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable(TValue, TValue, TKey, TKey, int, int): int

and must return -1,0,1 as spaceship operator

AbstractMap::toArray

public function toArray(): array

Return an array representing the values

AbstractMap::valueDiff

public function valueDiff(AbstractMap $compared): static

Return a map of all items where values are not in arguments map

AbstractMap::valueIntersect

public function valueIntersect(AbstractMap $compared): static

Return a map of all items where values are in argument map

AbstractMap::values

public function values(): Generator

Return an iterator of values

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Micoli\Multitude

A collection library for PHP.

Build StatusCoverage StatusLatest Stable VersionTotal DownloadsLatest Unstable VersionLicensePHP Version Require

Two types of collections are available:

  • Sets (MutableSet and ImmutableSet), are sequences of unique values. Values can be of any types.
  • Map (MutableMap and ImmutableMap), is a sequential collection of key-value pairs. Keys can be any type, but must be unique. Values can be of any types.

In both ImmutableSet and ImmutableMap, if a method alter the content af the inner values, a new instance is returned of the same type. Oppositely, in MutableSet and MutableMap, same methods are altering the inner values.

Methods are the most possible fluent.

Thanks to https://github.com/BenMorel for the main ideas used in that library, this is a complete rewrite of it's initial version.

Installation

This library is installable via Composer:

composer require micoli/multitude

Requirements

This library requires PHP 8.0 or later.

Project status

While this library is still under development, it is still in early development status. It follows semver version tagging.

Quick start

Constructor are only statics:

  • new MutableSet(['a','b','c'])
  • new MutableMap([2=>'a',3=>'b',4=>'c'])
  • new MutableMap([[2,'a'],['2','aa'],[3,'b'],['3','bb'],[4,'c'])

You can use fromTuples constructor if you need a strong typing for keys of your map, e.g. '2' key is different of 2.

Methods that accept a bool $throw parameter will trigger an exception if $throw == true or fails silently if $throw == false.

Example with an associative array

publicfunctiontestItShouldFullyWorkWithAssociativeArray(): void
{
/** @var ImmutableMap<string, array{value:int,tags:list<string>}> $map */$map = newImmutableMap([
['library', ['value' => 10, 'tags' => ['tag1']]],
['projects', ['value' => 5, 'tags' => ['tag2']]],
['gist', ['value' => 7, 'tags' => ['tag1', 'tag2']]],
['repository', ['value' => 7, 'tags' => ['tag3']]],
]);
$totalSum = $map
->filter(fn (array$project, mixed$category): bool => array_search('tag1', $project['tags']) !== false)
->reduce(fn (int$sum, mixed$project, mixed$category): int => $sum + $project['value'], 0);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
}

Example with an immutable map fully typed

File: Project.php

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
class Project
{
publicfunction__construct(
publicreadonlyint$value,
publicreadonlyTags$tags,
) {
}
}

File: Tags

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Set\ImmutableSet;
/** * @extends ImmutableSet<string> */class Tags extends ImmutableSet
{
}

File: Projects

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Map\ImmutableMap;
/** * @extends ImmutableMap<string, Project> */class Projects extends ImmutableMap
{
/** * Add or replace a value in the map */publicfunctionimprovedSet(string$newKey, Project$newValue): static
{
// do specific stuff, like logging or therreturn$this->set($newKey, $newValue);
}
}
publicfunctiontestItShouldFullyWorkWithObjects(): void
{
$map = newProjects([
['library', newProject(10, newTags(['tag1']))],
['projects', newProject(5, newTags(['tag2']))],
['gist', newProject(7, newTags(['tag1', 'tag2']))],
['repository', newProject(7, newTags(['tag3']))],
]);
$totalSum = $map
->filter(fn (Project$project, mixed$category): bool => $project->tags->hasValue('tag1'))
->reduce(fn (int$sum, Project$project, mixed$category): int => $sum + $project->value, 0);
self::assertInstanceOf(
Projects::class,
$map->filter(fn (Project$project, mixed$category): bool => true),
);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
$newMap = $map->improvedSet('NewType', newProject(10, newTags(['tag4'])));
self::assertCount(5, $newMap);
}

Available verbs

Verb parity

ImmutableMapMutableMapImmutableSetMutableSet
__construct[x][x][x][x]
append[x][x]
apply[x][x][x][x]
count[x][x][x][x]
filter[x][x][x][x]
first[x][x][x][x]
forEach[x][x][x][x]
fromIterable[x][x]
get[x][x][x][x]
getIterator[x][x][x][x]
getTuples[x][x]
hasIndex[x][x]
hasKey[x][x]
hasValue[x][x][x][x]
indexDiff[x][x]
indexIntersect[x][x]
isEmpty[x][x][x][x]
keyDiff[x][x]
keyIntersect[x][x]
keys[x][x][x][x]
ImmutableMapMutableMapImmutableSetMutableSet
last[x][x][x][x]
map[x][x][x][x]
offsetExists[x][x]
offsetGet[x][x]
offsetSet[x][x]
offsetUnset[x][x]
reduce[x][x][x][x]
remove[x][x]
removeKey[x][x]
removeValue[x][x]
set[x][x]
slice[x][x][x][x]
sort[x][x][x][x]
toArray[x][x][x][x]
toImmutable[x][x]
toMutable[x][x]
valueDiff[x][x][x][x]
valueIntersect[x][x][x][x]
values[x][x][x][x]

AbstractSet

AbstractMap

AbstractSet

AbstractSet::__construct

public function __construct(iterable $values = [])

AbstractSet::append

public function append(mixed $newValue, bool $throw = true): static

Append a value at the end of the set

AbstractSet::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractSet::count

public function count(): int

return the number of items in the set

AbstractSet::filter

public function filter(callable $callable): static

Filter the set using a callback function

AbstractSet::first

public function first(bool $throw = true): mixed

Return the first value in the set

AbstractSet::forEach

public function forEach(callable $callable): static

Apply a callback on set values

Callback receive $value and $index

AbstractSet::get

public function get(int $index, mixed $defaultValue = null): mixed

Return a value in the set by index

AbstractSet::getIterator

public function getIterator(): Traversable

Return an iterator for values

AbstractSet::hasIndex

public function hasIndex(int $index): bool

Return if a set contains an index

AbstractSet::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a set contains a value

AbstractSet::indexDiff

public function indexDiff(AbstractSet $compared): static

Return a set of all items where keys are not in argument set

AbstractSet::indexIntersect

public function indexIntersect(AbstractSet $compared): static

Return a map of all items where keys are in arguments map

AbstractSet::isEmpty

public function isEmpty(): bool

Return if a set is empty

AbstractSet::keys

public function keys(): Generator

Return an iterator of keys

AbstractSet::last

public function last(bool $throw = true): mixed

Return the latest value in the set

AbstractSet::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

Callback receive $value and $index

AbstractSet::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Set to a single value using a callback function

Callback receive $accumulator,$value and $index

AbstractSet::remove

public function remove(mixed $searchedValue, bool $throw = true): static

Remove a value in the set

AbstractSet::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the set

AbstractSet::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable (TValue, TValue, int, int): int

and must return -1,0,1 as spaceship operator

AbstractSet::toArray

public function toArray(): array

Return an array representing the values

AbstractSet::valueDiff

public function valueDiff(AbstractSet $compared): static

Return a Set of all items where values are not in argument set

AbstractSet::valueIntersect

public function valueIntersect(AbstractSet $compared): static

Return a set of all items where values are in argument set

AbstractSet::values

public function values(): Generator

Return an iterator of values

AbstractMap

AbstractMap::__construct

public function __construct(array $tuples = [])

AbstractMap::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractMap::count

public function count(): int

Return the number of items in the map

AbstractMap::filter

public function filter(callable $callable): static

Filter the map using a callback function

AbstractMap::first

public function first(bool $throw = true): mixed

Return the first value in the map

AbstractMap::forEach

public function forEach(callable $callable): static

Apply a callback on set values

AbstractMap::fromIterable

public static function fromIterable(iterable $values): static

Return a new instance from an array.

AbstractMap::get

public function get(mixed $searchedKey, mixed $defaultValue = null): mixed

Return a value in the map by index

AbstractMap::getIterator

public function getIterator(): Traversable

Return an iterator for values by keys

AbstractMap::getTuples

public function getTuples(): array

AbstractMap::hasKey

public function hasKey(mixed $searchedKey): bool

Return if a map contains a specific key

AbstractMap::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a map contains a specific value

AbstractMap::isEmpty

public function isEmpty(): bool

Return if a map is empty

AbstractMap::keyDiff

public function keyDiff(AbstractMap $compared): static

Return a map of all items where keys are not in argument map

AbstractMap::keyIntersect

public function keyIntersect(AbstractMap $compared): static

Return a map of all items where keys are in arguments map

AbstractMap::keys

public function keys(): Generator

Return an iterator of keys

AbstractMap::last

public function last(bool $throw = true): mixed

Return the latest value in the map

AbstractMap::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

AbstractMap::offsetExists

public function offsetExists(mixed $offset): bool

AbstractMap::offsetGet

public function offsetGet(mixed $offset): mixed

AbstractMap::offsetSet

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

AbstractMap::offsetUnset

public function offsetUnset(mixed $offset): void

AbstractMap::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Map to a single value using a callback function

Callback receive $accumulator,$value and $key

AbstractMap::removeKey

public function removeKey(mixed $searchedKey): static

Remove a value in the map by key

AbstractMap::removeValue

public function removeValue(mixed $searchedValue): static

Remove a value in the map by value

AbstractMap::set

public function set(mixed $newKey, mixed $newValue): static

Add or replace a value in the map

AbstractMap::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the map

AbstractMap::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable(TValue, TValue, TKey, TKey, int, int): int

and must return -1,0,1 as spaceship operator

AbstractMap::toArray

public function toArray(): array

Return an array representing the values

AbstractMap::valueDiff

public function valueDiff(AbstractMap $compared): static

Return a map of all items where values are not in arguments map

AbstractMap::valueIntersect

public function valueIntersect(AbstractMap $compared): static

Return a map of all items where values are in argument map

AbstractMap::values

public function values(): Generator

Return an iterator of values

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Micoli\Multitude

A collection library for PHP.

Build StatusCoverage StatusLatest Stable VersionTotal DownloadsLatest Unstable VersionLicensePHP Version Require

Two types of collections are available:

  • Sets (MutableSet and ImmutableSet), are sequences of unique values. Values can be of any types.
  • Map (MutableMap and ImmutableMap), is a sequential collection of key-value pairs. Keys can be any type, but must be unique. Values can be of any types.

In both ImmutableSet and ImmutableMap, if a method alter the content af the inner values, a new instance is returned of the same type. Oppositely, in MutableSet and MutableMap, same methods are altering the inner values.

Methods are the most possible fluent.

Thanks to https://github.com/BenMorel for the main ideas used in that library, this is a complete rewrite of it's initial version.

Installation

This library is installable via Composer:

composer require micoli/multitude

Requirements

This library requires PHP 8.0 or later.

Project status

While this library is still under development, it is still in early development status. It follows semver version tagging.

Quick start

Constructor are only statics:

  • new MutableSet(['a','b','c'])
  • new MutableMap([2=>'a',3=>'b',4=>'c'])
  • new MutableMap([[2,'a'],['2','aa'],[3,'b'],['3','bb'],[4,'c'])

You can use fromTuples constructor if you need a strong typing for keys of your map, e.g. '2' key is different of 2.

Methods that accept a bool $throw parameter will trigger an exception if $throw == true or fails silently if $throw == false.

Example with an associative array

publicfunctiontestItShouldFullyWorkWithAssociativeArray(): void
{
/** @var ImmutableMap<string, array{value:int,tags:list<string>}> $map */$map = newImmutableMap([
['library', ['value' => 10, 'tags' => ['tag1']]],
['projects', ['value' => 5, 'tags' => ['tag2']]],
['gist', ['value' => 7, 'tags' => ['tag1', 'tag2']]],
['repository', ['value' => 7, 'tags' => ['tag3']]],
]);
$totalSum = $map
->filter(fn (array$project, mixed$category): bool => array_search('tag1', $project['tags']) !== false)
->reduce(fn (int$sum, mixed$project, mixed$category): int => $sum + $project['value'], 0);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
}

Example with an immutable map fully typed

File: Project.php

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
class Project
{
publicfunction__construct(
publicreadonlyint$value,
publicreadonlyTags$tags,
) {
}
}

File: Tags

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Set\ImmutableSet;
/** * @extends ImmutableSet<string> */class Tags extends ImmutableSet
{
}

File: Projects

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Map\ImmutableMap;
/** * @extends ImmutableMap<string, Project> */class Projects extends ImmutableMap
{
/** * Add or replace a value in the map */publicfunctionimprovedSet(string$newKey, Project$newValue): static
{
// do specific stuff, like logging or therreturn$this->set($newKey, $newValue);
}
}
publicfunctiontestItShouldFullyWorkWithObjects(): void
{
$map = newProjects([
['library', newProject(10, newTags(['tag1']))],
['projects', newProject(5, newTags(['tag2']))],
['gist', newProject(7, newTags(['tag1', 'tag2']))],
['repository', newProject(7, newTags(['tag3']))],
]);
$totalSum = $map
->filter(fn (Project$project, mixed$category): bool => $project->tags->hasValue('tag1'))
->reduce(fn (int$sum, Project$project, mixed$category): int => $sum + $project->value, 0);
self::assertInstanceOf(
Projects::class,
$map->filter(fn (Project$project, mixed$category): bool => true),
);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
$newMap = $map->improvedSet('NewType', newProject(10, newTags(['tag4'])));
self::assertCount(5, $newMap);
}

Available verbs

Verb parity

ImmutableMapMutableMapImmutableSetMutableSet
__construct[x][x][x][x]
append[x][x]
apply[x][x][x][x]
count[x][x][x][x]
filter[x][x][x][x]
first[x][x][x][x]
forEach[x][x][x][x]
fromIterable[x][x]
get[x][x][x][x]
getIterator[x][x][x][x]
getTuples[x][x]
hasIndex[x][x]
hasKey[x][x]
hasValue[x][x][x][x]
indexDiff[x][x]
indexIntersect[x][x]
isEmpty[x][x][x][x]
keyDiff[x][x]
keyIntersect[x][x]
keys[x][x][x][x]
ImmutableMapMutableMapImmutableSetMutableSet
last[x][x][x][x]
map[x][x][x][x]
offsetExists[x][x]
offsetGet[x][x]
offsetSet[x][x]
offsetUnset[x][x]
reduce[x][x][x][x]
remove[x][x]
removeKey[x][x]
removeValue[x][x]
set[x][x]
slice[x][x][x][x]
sort[x][x][x][x]
toArray[x][x][x][x]
toImmutable[x][x]
toMutable[x][x]
valueDiff[x][x][x][x]
valueIntersect[x][x][x][x]
values[x][x][x][x]

AbstractSet

AbstractMap

AbstractSet

AbstractSet::__construct

public function __construct(iterable $values = [])

AbstractSet::append

public function append(mixed $newValue, bool $throw = true): static

Append a value at the end of the set

AbstractSet::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractSet::count

public function count(): int

return the number of items in the set

AbstractSet::filter

public function filter(callable $callable): static

Filter the set using a callback function

AbstractSet::first

public function first(bool $throw = true): mixed

Return the first value in the set

AbstractSet::forEach

public function forEach(callable $callable): static

Apply a callback on set values

Callback receive $value and $index

AbstractSet::get

public function get(int $index, mixed $defaultValue = null): mixed

Return a value in the set by index

AbstractSet::getIterator

public function getIterator(): Traversable

Return an iterator for values

AbstractSet::hasIndex

public function hasIndex(int $index): bool

Return if a set contains an index

AbstractSet::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a set contains a value

AbstractSet::indexDiff

public function indexDiff(AbstractSet $compared): static

Return a set of all items where keys are not in argument set

AbstractSet::indexIntersect

public function indexIntersect(AbstractSet $compared): static

Return a map of all items where keys are in arguments map

AbstractSet::isEmpty

public function isEmpty(): bool

Return if a set is empty

AbstractSet::keys

public function keys(): Generator

Return an iterator of keys

AbstractSet::last

public function last(bool $throw = true): mixed

Return the latest value in the set

AbstractSet::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

Callback receive $value and $index

AbstractSet::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Set to a single value using a callback function

Callback receive $accumulator,$value and $index

AbstractSet::remove

public function remove(mixed $searchedValue, bool $throw = true): static

Remove a value in the set

AbstractSet::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the set

AbstractSet::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable (TValue, TValue, int, int): int

and must return -1,0,1 as spaceship operator

AbstractSet::toArray

public function toArray(): array

Return an array representing the values

AbstractSet::valueDiff

public function valueDiff(AbstractSet $compared): static

Return a Set of all items where values are not in argument set

AbstractSet::valueIntersect

public function valueIntersect(AbstractSet $compared): static

Return a set of all items where values are in argument set

AbstractSet::values

public function values(): Generator

Return an iterator of values

AbstractMap

AbstractMap::__construct

public function __construct(array $tuples = [])

AbstractMap::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractMap::count

public function count(): int

Return the number of items in the map

AbstractMap::filter

public function filter(callable $callable): static

Filter the map using a callback function

AbstractMap::first

public function first(bool $throw = true): mixed

Return the first value in the map

AbstractMap::forEach

public function forEach(callable $callable): static

Apply a callback on set values

AbstractMap::fromIterable

public static function fromIterable(iterable $values): static

Return a new instance from an array.

AbstractMap::get

public function get(mixed $searchedKey, mixed $defaultValue = null): mixed

Return a value in the map by index

AbstractMap::getIterator

public function getIterator(): Traversable

Return an iterator for values by keys

AbstractMap::getTuples

public function getTuples(): array

AbstractMap::hasKey

public function hasKey(mixed $searchedKey): bool

Return if a map contains a specific key

AbstractMap::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a map contains a specific value

AbstractMap::isEmpty

public function isEmpty(): bool

Return if a map is empty

AbstractMap::keyDiff

public function keyDiff(AbstractMap $compared): static

Return a map of all items where keys are not in argument map

AbstractMap::keyIntersect

public function keyIntersect(AbstractMap $compared): static

Return a map of all items where keys are in arguments map

AbstractMap::keys

public function keys(): Generator

Return an iterator of keys

AbstractMap::last

public function last(bool $throw = true): mixed

Return the latest value in the map

AbstractMap::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

AbstractMap::offsetExists

public function offsetExists(mixed $offset): bool

AbstractMap::offsetGet

public function offsetGet(mixed $offset): mixed

AbstractMap::offsetSet

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

AbstractMap::offsetUnset

public function offsetUnset(mixed $offset): void

AbstractMap::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Map to a single value using a callback function

Callback receive $accumulator,$value and $key

AbstractMap::removeKey

public function removeKey(mixed $searchedKey): static

Remove a value in the map by key

AbstractMap::removeValue

public function removeValue(mixed $searchedValue): static

Remove a value in the map by value

AbstractMap::set

public function set(mixed $newKey, mixed $newValue): static

Add or replace a value in the map

AbstractMap::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the map

AbstractMap::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable(TValue, TValue, TKey, TKey, int, int): int

and must return -1,0,1 as spaceship operator

AbstractMap::toArray

public function toArray(): array

Return an array representing the values

AbstractMap::valueDiff

public function valueDiff(AbstractMap $compared): static

Return a map of all items where values are not in arguments map

AbstractMap::valueIntersect

public function valueIntersect(AbstractMap $compared): static

Return a map of all items where values are in argument map

AbstractMap::values

public function values(): Generator

Return an iterator of values

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Micoli\Multitude

A collection library for PHP.

Build StatusCoverage StatusLatest Stable VersionTotal DownloadsLatest Unstable VersionLicensePHP Version Require

Two types of collections are available:

  • Sets (MutableSet and ImmutableSet), are sequences of unique values. Values can be of any types.
  • Map (MutableMap and ImmutableMap), is a sequential collection of key-value pairs. Keys can be any type, but must be unique. Values can be of any types.

In both ImmutableSet and ImmutableMap, if a method alter the content af the inner values, a new instance is returned of the same type. Oppositely, in MutableSet and MutableMap, same methods are altering the inner values.

Methods are the most possible fluent.

Thanks to https://github.com/BenMorel for the main ideas used in that library, this is a complete rewrite of it's initial version.

Installation

This library is installable via Composer:

composer require micoli/multitude

Requirements

This library requires PHP 8.0 or later.

Project status

While this library is still under development, it is still in early development status. It follows semver version tagging.

Quick start

Constructor are only statics:

  • new MutableSet(['a','b','c'])
  • new MutableMap([2=>'a',3=>'b',4=>'c'])
  • new MutableMap([[2,'a'],['2','aa'],[3,'b'],['3','bb'],[4,'c'])

You can use fromTuples constructor if you need a strong typing for keys of your map, e.g. '2' key is different of 2.

Methods that accept a bool $throw parameter will trigger an exception if $throw == true or fails silently if $throw == false.

Example with an associative array

publicfunctiontestItShouldFullyWorkWithAssociativeArray(): void
{
/** @var ImmutableMap<string, array{value:int,tags:list<string>}> $map */$map = newImmutableMap([
['library', ['value' => 10, 'tags' => ['tag1']]],
['projects', ['value' => 5, 'tags' => ['tag2']]],
['gist', ['value' => 7, 'tags' => ['tag1', 'tag2']]],
['repository', ['value' => 7, 'tags' => ['tag3']]],
]);
$totalSum = $map
->filter(fn (array$project, mixed$category): bool => array_search('tag1', $project['tags']) !== false)
->reduce(fn (int$sum, mixed$project, mixed$category): int => $sum + $project['value'], 0);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
}

Example with an immutable map fully typed

File: Project.php

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
class Project
{
publicfunction__construct(
publicreadonlyint$value,
publicreadonlyTags$tags,
) {
}
}

File: Tags

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Set\ImmutableSet;
/** * @extends ImmutableSet<string> */class Tags extends ImmutableSet
{
}

File: Projects

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Map\ImmutableMap;
/** * @extends ImmutableMap<string, Project> */class Projects extends ImmutableMap
{
/** * Add or replace a value in the map */publicfunctionimprovedSet(string$newKey, Project$newValue): static
{
// do specific stuff, like logging or therreturn$this->set($newKey, $newValue);
}
}
publicfunctiontestItShouldFullyWorkWithObjects(): void
{
$map = newProjects([
['library', newProject(10, newTags(['tag1']))],
['projects', newProject(5, newTags(['tag2']))],
['gist', newProject(7, newTags(['tag1', 'tag2']))],
['repository', newProject(7, newTags(['tag3']))],
]);
$totalSum = $map
->filter(fn (Project$project, mixed$category): bool => $project->tags->hasValue('tag1'))
->reduce(fn (int$sum, Project$project, mixed$category): int => $sum + $project->value, 0);
self::assertInstanceOf(
Projects::class,
$map->filter(fn (Project$project, mixed$category): bool => true),
);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
$newMap = $map->improvedSet('NewType', newProject(10, newTags(['tag4'])));
self::assertCount(5, $newMap);
}

Available verbs

Verb parity

ImmutableMapMutableMapImmutableSetMutableSet
__construct[x][x][x][x]
append[x][x]
apply[x][x][x][x]
count[x][x][x][x]
filter[x][x][x][x]
first[x][x][x][x]
forEach[x][x][x][x]
fromIterable[x][x]
get[x][x][x][x]
getIterator[x][x][x][x]
getTuples[x][x]
hasIndex[x][x]
hasKey[x][x]
hasValue[x][x][x][x]
indexDiff[x][x]
indexIntersect[x][x]
isEmpty[x][x][x][x]
keyDiff[x][x]
keyIntersect[x][x]
keys[x][x][x][x]
ImmutableMapMutableMapImmutableSetMutableSet
last[x][x][x][x]
map[x][x][x][x]
offsetExists[x][x]
offsetGet[x][x]
offsetSet[x][x]
offsetUnset[x][x]
reduce[x][x][x][x]
remove[x][x]
removeKey[x][x]
removeValue[x][x]
set[x][x]
slice[x][x][x][x]
sort[x][x][x][x]
toArray[x][x][x][x]
toImmutable[x][x]
toMutable[x][x]
valueDiff[x][x][x][x]
valueIntersect[x][x][x][x]
values[x][x][x][x]

AbstractSet

AbstractMap

AbstractSet

AbstractSet::__construct

public function __construct(iterable $values = [])

AbstractSet::append

public function append(mixed $newValue, bool $throw = true): static

Append a value at the end of the set

AbstractSet::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractSet::count

public function count(): int

return the number of items in the set

AbstractSet::filter

public function filter(callable $callable): static

Filter the set using a callback function

AbstractSet::first

public function first(bool $throw = true): mixed

Return the first value in the set

AbstractSet::forEach

public function forEach(callable $callable): static

Apply a callback on set values

Callback receive $value and $index

AbstractSet::get

public function get(int $index, mixed $defaultValue = null): mixed

Return a value in the set by index

AbstractSet::getIterator

public function getIterator(): Traversable

Return an iterator for values

AbstractSet::hasIndex

public function hasIndex(int $index): bool

Return if a set contains an index

AbstractSet::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a set contains a value

AbstractSet::indexDiff

public function indexDiff(AbstractSet $compared): static

Return a set of all items where keys are not in argument set

AbstractSet::indexIntersect

public function indexIntersect(AbstractSet $compared): static

Return a map of all items where keys are in arguments map

AbstractSet::isEmpty

public function isEmpty(): bool

Return if a set is empty

AbstractSet::keys

public function keys(): Generator

Return an iterator of keys

AbstractSet::last

public function last(bool $throw = true): mixed

Return the latest value in the set

AbstractSet::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

Callback receive $value and $index

AbstractSet::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Set to a single value using a callback function

Callback receive $accumulator,$value and $index

AbstractSet::remove

public function remove(mixed $searchedValue, bool $throw = true): static

Remove a value in the set

AbstractSet::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the set

AbstractSet::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable (TValue, TValue, int, int): int

and must return -1,0,1 as spaceship operator

AbstractSet::toArray

public function toArray(): array

Return an array representing the values

AbstractSet::valueDiff

public function valueDiff(AbstractSet $compared): static

Return a Set of all items where values are not in argument set

AbstractSet::valueIntersect

public function valueIntersect(AbstractSet $compared): static

Return a set of all items where values are in argument set

AbstractSet::values

public function values(): Generator

Return an iterator of values

AbstractMap

AbstractMap::__construct

public function __construct(array $tuples = [])

AbstractMap::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractMap::count

public function count(): int

Return the number of items in the map

AbstractMap::filter

public function filter(callable $callable): static

Filter the map using a callback function

AbstractMap::first

public function first(bool $throw = true): mixed

Return the first value in the map

AbstractMap::forEach

public function forEach(callable $callable): static

Apply a callback on set values

AbstractMap::fromIterable

public static function fromIterable(iterable $values): static

Return a new instance from an array.

AbstractMap::get

public function get(mixed $searchedKey, mixed $defaultValue = null): mixed

Return a value in the map by index

AbstractMap::getIterator

public function getIterator(): Traversable

Return an iterator for values by keys

AbstractMap::getTuples

public function getTuples(): array

AbstractMap::hasKey

public function hasKey(mixed $searchedKey): bool

Return if a map contains a specific key

AbstractMap::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a map contains a specific value

AbstractMap::isEmpty

public function isEmpty(): bool

Return if a map is empty

AbstractMap::keyDiff

public function keyDiff(AbstractMap $compared): static

Return a map of all items where keys are not in argument map

AbstractMap::keyIntersect

public function keyIntersect(AbstractMap $compared): static

Return a map of all items where keys are in arguments map

AbstractMap::keys

public function keys(): Generator

Return an iterator of keys

AbstractMap::last

public function last(bool $throw = true): mixed

Return the latest value in the map

AbstractMap::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

AbstractMap::offsetExists

public function offsetExists(mixed $offset): bool

AbstractMap::offsetGet

public function offsetGet(mixed $offset): mixed

AbstractMap::offsetSet

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

AbstractMap::offsetUnset

public function offsetUnset(mixed $offset): void

AbstractMap::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Map to a single value using a callback function

Callback receive $accumulator,$value and $key

AbstractMap::removeKey

public function removeKey(mixed $searchedKey): static

Remove a value in the map by key

AbstractMap::removeValue

public function removeValue(mixed $searchedValue): static

Remove a value in the map by value

AbstractMap::set

public function set(mixed $newKey, mixed $newValue): static

Add or replace a value in the map

AbstractMap::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the map

AbstractMap::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable(TValue, TValue, TKey, TKey, int, int): int

and must return -1,0,1 as spaceship operator

AbstractMap::toArray

public function toArray(): array

Return an array representing the values

AbstractMap::valueDiff

public function valueDiff(AbstractMap $compared): static

Return a map of all items where values are not in arguments map

AbstractMap::valueIntersect

public function valueIntersect(AbstractMap $compared): static

Return a map of all items where values are in argument map

AbstractMap::values

public function values(): Generator

Return an iterator of values

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Micoli\Multitude

A collection library for PHP.

Build StatusCoverage StatusLatest Stable VersionTotal DownloadsLatest Unstable VersionLicensePHP Version Require

Two types of collections are available:

  • Sets (MutableSet and ImmutableSet), are sequences of unique values. Values can be of any types.
  • Map (MutableMap and ImmutableMap), is a sequential collection of key-value pairs. Keys can be any type, but must be unique. Values can be of any types.

In both ImmutableSet and ImmutableMap, if a method alter the content af the inner values, a new instance is returned of the same type. Oppositely, in MutableSet and MutableMap, same methods are altering the inner values.

Methods are the most possible fluent.

Thanks to https://github.com/BenMorel for the main ideas used in that library, this is a complete rewrite of it's initial version.

Installation

This library is installable via Composer:

composer require micoli/multitude

Requirements

This library requires PHP 8.0 or later.

Project status

While this library is still under development, it is still in early development status. It follows semver version tagging.

Quick start

Constructor are only statics:

  • new MutableSet(['a','b','c'])
  • new MutableMap([2=>'a',3=>'b',4=>'c'])
  • new MutableMap([[2,'a'],['2','aa'],[3,'b'],['3','bb'],[4,'c'])

You can use fromTuples constructor if you need a strong typing for keys of your map, e.g. '2' key is different of 2.

Methods that accept a bool $throw parameter will trigger an exception if $throw == true or fails silently if $throw == false.

Example with an associative array

publicfunctiontestItShouldFullyWorkWithAssociativeArray(): void
{
/** @var ImmutableMap<string, array{value:int,tags:list<string>}> $map */$map = newImmutableMap([
['library', ['value' => 10, 'tags' => ['tag1']]],
['projects', ['value' => 5, 'tags' => ['tag2']]],
['gist', ['value' => 7, 'tags' => ['tag1', 'tag2']]],
['repository', ['value' => 7, 'tags' => ['tag3']]],
]);
$totalSum = $map
->filter(fn (array$project, mixed$category): bool => array_search('tag1', $project['tags']) !== false)
->reduce(fn (int$sum, mixed$project, mixed$category): int => $sum + $project['value'], 0);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
}

Example with an immutable map fully typed

File: Project.php

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
class Project
{
publicfunction__construct(
publicreadonlyint$value,
publicreadonlyTags$tags,
) {
}
}

File: Tags

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Set\ImmutableSet;
/** * @extends ImmutableSet<string> */class Tags extends ImmutableSet
{
}

File: Projects

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Map\ImmutableMap;
/** * @extends ImmutableMap<string, Project> */class Projects extends ImmutableMap
{
/** * Add or replace a value in the map */publicfunctionimprovedSet(string$newKey, Project$newValue): static
{
// do specific stuff, like logging or therreturn$this->set($newKey, $newValue);
}
}
publicfunctiontestItShouldFullyWorkWithObjects(): void
{
$map = newProjects([
['library', newProject(10, newTags(['tag1']))],
['projects', newProject(5, newTags(['tag2']))],
['gist', newProject(7, newTags(['tag1', 'tag2']))],
['repository', newProject(7, newTags(['tag3']))],
]);
$totalSum = $map
->filter(fn (Project$project, mixed$category): bool => $project->tags->hasValue('tag1'))
->reduce(fn (int$sum, Project$project, mixed$category): int => $sum + $project->value, 0);
self::assertInstanceOf(
Projects::class,
$map->filter(fn (Project$project, mixed$category): bool => true),
);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
$newMap = $map->improvedSet('NewType', newProject(10, newTags(['tag4'])));
self::assertCount(5, $newMap);
}

Available verbs

Verb parity

ImmutableMapMutableMapImmutableSetMutableSet
__construct[x][x][x][x]
append[x][x]
apply[x][x][x][x]
count[x][x][x][x]
filter[x][x][x][x]
first[x][x][x][x]
forEach[x][x][x][x]
fromIterable[x][x]
get[x][x][x][x]
getIterator[x][x][x][x]
getTuples[x][x]
hasIndex[x][x]
hasKey[x][x]
hasValue[x][x][x][x]
indexDiff[x][x]
indexIntersect[x][x]
isEmpty[x][x][x][x]
keyDiff[x][x]
keyIntersect[x][x]
keys[x][x][x][x]
ImmutableMapMutableMapImmutableSetMutableSet
last[x][x][x][x]
map[x][x][x][x]
offsetExists[x][x]
offsetGet[x][x]
offsetSet[x][x]
offsetUnset[x][x]
reduce[x][x][x][x]
remove[x][x]
removeKey[x][x]
removeValue[x][x]
set[x][x]
slice[x][x][x][x]
sort[x][x][x][x]
toArray[x][x][x][x]
toImmutable[x][x]
toMutable[x][x]
valueDiff[x][x][x][x]
valueIntersect[x][x][x][x]
values[x][x][x][x]

AbstractSet

AbstractMap

AbstractSet

AbstractSet::__construct

public function __construct(iterable $values = [])

AbstractSet::append

public function append(mixed $newValue, bool $throw = true): static

Append a value at the end of the set

AbstractSet::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractSet::count

public function count(): int

return the number of items in the set

AbstractSet::filter

public function filter(callable $callable): static

Filter the set using a callback function

AbstractSet::first

public function first(bool $throw = true): mixed

Return the first value in the set

AbstractSet::forEach

public function forEach(callable $callable): static

Apply a callback on set values

Callback receive $value and $index

AbstractSet::get

public function get(int $index, mixed $defaultValue = null): mixed

Return a value in the set by index

AbstractSet::getIterator

public function getIterator(): Traversable

Return an iterator for values

AbstractSet::hasIndex

public function hasIndex(int $index): bool

Return if a set contains an index

AbstractSet::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a set contains a value

AbstractSet::indexDiff

public function indexDiff(AbstractSet $compared): static

Return a set of all items where keys are not in argument set

AbstractSet::indexIntersect

public function indexIntersect(AbstractSet $compared): static

Return a map of all items where keys are in arguments map

AbstractSet::isEmpty

public function isEmpty(): bool

Return if a set is empty

AbstractSet::keys

public function keys(): Generator

Return an iterator of keys

AbstractSet::last

public function last(bool $throw = true): mixed

Return the latest value in the set

AbstractSet::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

Callback receive $value and $index

AbstractSet::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Set to a single value using a callback function

Callback receive $accumulator,$value and $index

AbstractSet::remove

public function remove(mixed $searchedValue, bool $throw = true): static

Remove a value in the set

AbstractSet::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the set

AbstractSet::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable (TValue, TValue, int, int): int

and must return -1,0,1 as spaceship operator

AbstractSet::toArray

public function toArray(): array

Return an array representing the values

AbstractSet::valueDiff

public function valueDiff(AbstractSet $compared): static

Return a Set of all items where values are not in argument set

AbstractSet::valueIntersect

public function valueIntersect(AbstractSet $compared): static

Return a set of all items where values are in argument set

AbstractSet::values

public function values(): Generator

Return an iterator of values

AbstractMap

AbstractMap::__construct

public function __construct(array $tuples = [])

AbstractMap::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractMap::count

public function count(): int

Return the number of items in the map

AbstractMap::filter

public function filter(callable $callable): static

Filter the map using a callback function

AbstractMap::first

public function first(bool $throw = true): mixed

Return the first value in the map

AbstractMap::forEach

public function forEach(callable $callable): static

Apply a callback on set values

AbstractMap::fromIterable

public static function fromIterable(iterable $values): static

Return a new instance from an array.

AbstractMap::get

public function get(mixed $searchedKey, mixed $defaultValue = null): mixed

Return a value in the map by index

AbstractMap::getIterator

public function getIterator(): Traversable

Return an iterator for values by keys

AbstractMap::getTuples

public function getTuples(): array

AbstractMap::hasKey

public function hasKey(mixed $searchedKey): bool

Return if a map contains a specific key

AbstractMap::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a map contains a specific value

AbstractMap::isEmpty

public function isEmpty(): bool

Return if a map is empty

AbstractMap::keyDiff

public function keyDiff(AbstractMap $compared): static

Return a map of all items where keys are not in argument map

AbstractMap::keyIntersect

public function keyIntersect(AbstractMap $compared): static

Return a map of all items where keys are in arguments map

AbstractMap::keys

public function keys(): Generator

Return an iterator of keys

AbstractMap::last

public function last(bool $throw = true): mixed

Return the latest value in the map

AbstractMap::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

AbstractMap::offsetExists

public function offsetExists(mixed $offset): bool

AbstractMap::offsetGet

public function offsetGet(mixed $offset): mixed

AbstractMap::offsetSet

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

AbstractMap::offsetUnset

public function offsetUnset(mixed $offset): void

AbstractMap::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Map to a single value using a callback function

Callback receive $accumulator,$value and $key

AbstractMap::removeKey

public function removeKey(mixed $searchedKey): static

Remove a value in the map by key

AbstractMap::removeValue

public function removeValue(mixed $searchedValue): static

Remove a value in the map by value

AbstractMap::set

public function set(mixed $newKey, mixed $newValue): static

Add or replace a value in the map

AbstractMap::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the map

AbstractMap::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable(TValue, TValue, TKey, TKey, int, int): int

and must return -1,0,1 as spaceship operator

AbstractMap::toArray

public function toArray(): array

Return an array representing the values

AbstractMap::valueDiff

public function valueDiff(AbstractMap $compared): static

Return a map of all items where values are not in arguments map

AbstractMap::valueIntersect

public function valueIntersect(AbstractMap $compared): static

Return a map of all items where values are in argument map

AbstractMap::values

public function values(): Generator

Return an iterator of values

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Micoli\Multitude

A collection library for PHP.

Build StatusCoverage StatusLatest Stable VersionTotal DownloadsLatest Unstable VersionLicensePHP Version Require

Two types of collections are available:

  • Sets (MutableSet and ImmutableSet), are sequences of unique values. Values can be of any types.
  • Map (MutableMap and ImmutableMap), is a sequential collection of key-value pairs. Keys can be any type, but must be unique. Values can be of any types.

In both ImmutableSet and ImmutableMap, if a method alter the content af the inner values, a new instance is returned of the same type. Oppositely, in MutableSet and MutableMap, same methods are altering the inner values.

Methods are the most possible fluent.

Thanks to https://github.com/BenMorel for the main ideas used in that library, this is a complete rewrite of it's initial version.

Installation

This library is installable via Composer:

composer require micoli/multitude

Requirements

This library requires PHP 8.0 or later.

Project status

While this library is still under development, it is still in early development status. It follows semver version tagging.

Quick start

Constructor are only statics:

  • new MutableSet(['a','b','c'])
  • new MutableMap([2=>'a',3=>'b',4=>'c'])
  • new MutableMap([[2,'a'],['2','aa'],[3,'b'],['3','bb'],[4,'c'])

You can use fromTuples constructor if you need a strong typing for keys of your map, e.g. '2' key is different of 2.

Methods that accept a bool $throw parameter will trigger an exception if $throw == true or fails silently if $throw == false.

Example with an associative array

publicfunctiontestItShouldFullyWorkWithAssociativeArray(): void
{
/** @var ImmutableMap<string, array{value:int,tags:list<string>}> $map */$map = newImmutableMap([
['library', ['value' => 10, 'tags' => ['tag1']]],
['projects', ['value' => 5, 'tags' => ['tag2']]],
['gist', ['value' => 7, 'tags' => ['tag1', 'tag2']]],
['repository', ['value' => 7, 'tags' => ['tag3']]],
]);
$totalSum = $map
->filter(fn (array$project, mixed$category): bool => array_search('tag1', $project['tags']) !== false)
->reduce(fn (int$sum, mixed$project, mixed$category): int => $sum + $project['value'], 0);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
}

Example with an immutable map fully typed

File: Project.php

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
class Project
{
publicfunction__construct(
publicreadonlyint$value,
publicreadonlyTags$tags,
) {
}
}

File: Tags

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Set\ImmutableSet;
/** * @extends ImmutableSet<string> */class Tags extends ImmutableSet
{
}

File: Projects

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Map\ImmutableMap;
/** * @extends ImmutableMap<string, Project> */class Projects extends ImmutableMap
{
/** * Add or replace a value in the map */publicfunctionimprovedSet(string$newKey, Project$newValue): static
{
// do specific stuff, like logging or therreturn$this->set($newKey, $newValue);
}
}
publicfunctiontestItShouldFullyWorkWithObjects(): void
{
$map = newProjects([
['library', newProject(10, newTags(['tag1']))],
['projects', newProject(5, newTags(['tag2']))],
['gist', newProject(7, newTags(['tag1', 'tag2']))],
['repository', newProject(7, newTags(['tag3']))],
]);
$totalSum = $map
->filter(fn (Project$project, mixed$category): bool => $project->tags->hasValue('tag1'))
->reduce(fn (int$sum, Project$project, mixed$category): int => $sum + $project->value, 0);
self::assertInstanceOf(
Projects::class,
$map->filter(fn (Project$project, mixed$category): bool => true),
);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
$newMap = $map->improvedSet('NewType', newProject(10, newTags(['tag4'])));
self::assertCount(5, $newMap);
}

Available verbs

Verb parity

ImmutableMapMutableMapImmutableSetMutableSet
__construct[x][x][x][x]
append[x][x]
apply[x][x][x][x]
count[x][x][x][x]
filter[x][x][x][x]
first[x][x][x][x]
forEach[x][x][x][x]
fromIterable[x][x]
get[x][x][x][x]
getIterator[x][x][x][x]
getTuples[x][x]
hasIndex[x][x]
hasKey[x][x]
hasValue[x][x][x][x]
indexDiff[x][x]
indexIntersect[x][x]
isEmpty[x][x][x][x]
keyDiff[x][x]
keyIntersect[x][x]
keys[x][x][x][x]
ImmutableMapMutableMapImmutableSetMutableSet
last[x][x][x][x]
map[x][x][x][x]
offsetExists[x][x]
offsetGet[x][x]
offsetSet[x][x]
offsetUnset[x][x]
reduce[x][x][x][x]
remove[x][x]
removeKey[x][x]
removeValue[x][x]
set[x][x]
slice[x][x][x][x]
sort[x][x][x][x]
toArray[x][x][x][x]
toImmutable[x][x]
toMutable[x][x]
valueDiff[x][x][x][x]
valueIntersect[x][x][x][x]
values[x][x][x][x]

AbstractSet

AbstractMap

AbstractSet

AbstractSet::__construct

public function __construct(iterable $values = [])

AbstractSet::append

public function append(mixed $newValue, bool $throw = true): static

Append a value at the end of the set

AbstractSet::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractSet::count

public function count(): int

return the number of items in the set

AbstractSet::filter

public function filter(callable $callable): static

Filter the set using a callback function

AbstractSet::first

public function first(bool $throw = true): mixed

Return the first value in the set

AbstractSet::forEach

public function forEach(callable $callable): static

Apply a callback on set values

Callback receive $value and $index

AbstractSet::get

public function get(int $index, mixed $defaultValue = null): mixed

Return a value in the set by index

AbstractSet::getIterator

public function getIterator(): Traversable

Return an iterator for values

AbstractSet::hasIndex

public function hasIndex(int $index): bool

Return if a set contains an index

AbstractSet::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a set contains a value

AbstractSet::indexDiff

public function indexDiff(AbstractSet $compared): static

Return a set of all items where keys are not in argument set

AbstractSet::indexIntersect

public function indexIntersect(AbstractSet $compared): static

Return a map of all items where keys are in arguments map

AbstractSet::isEmpty

public function isEmpty(): bool

Return if a set is empty

AbstractSet::keys

public function keys(): Generator

Return an iterator of keys

AbstractSet::last

public function last(bool $throw = true): mixed

Return the latest value in the set

AbstractSet::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

Callback receive $value and $index

AbstractSet::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Set to a single value using a callback function

Callback receive $accumulator,$value and $index

AbstractSet::remove

public function remove(mixed $searchedValue, bool $throw = true): static

Remove a value in the set

AbstractSet::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the set

AbstractSet::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable (TValue, TValue, int, int): int

and must return -1,0,1 as spaceship operator

AbstractSet::toArray

public function toArray(): array

Return an array representing the values

AbstractSet::valueDiff

public function valueDiff(AbstractSet $compared): static

Return a Set of all items where values are not in argument set

AbstractSet::valueIntersect

public function valueIntersect(AbstractSet $compared): static

Return a set of all items where values are in argument set

AbstractSet::values

public function values(): Generator

Return an iterator of values

AbstractMap

AbstractMap::__construct

public function __construct(array $tuples = [])

AbstractMap::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractMap::count

public function count(): int

Return the number of items in the map

AbstractMap::filter

public function filter(callable $callable): static

Filter the map using a callback function

AbstractMap::first

public function first(bool $throw = true): mixed

Return the first value in the map

AbstractMap::forEach

public function forEach(callable $callable): static

Apply a callback on set values

AbstractMap::fromIterable

public static function fromIterable(iterable $values): static

Return a new instance from an array.

AbstractMap::get

public function get(mixed $searchedKey, mixed $defaultValue = null): mixed

Return a value in the map by index

AbstractMap::getIterator

public function getIterator(): Traversable

Return an iterator for values by keys

AbstractMap::getTuples

public function getTuples(): array

AbstractMap::hasKey

public function hasKey(mixed $searchedKey): bool

Return if a map contains a specific key

AbstractMap::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a map contains a specific value

AbstractMap::isEmpty

public function isEmpty(): bool

Return if a map is empty

AbstractMap::keyDiff

public function keyDiff(AbstractMap $compared): static

Return a map of all items where keys are not in argument map

AbstractMap::keyIntersect

public function keyIntersect(AbstractMap $compared): static

Return a map of all items where keys are in arguments map

AbstractMap::keys

public function keys(): Generator

Return an iterator of keys

AbstractMap::last

public function last(bool $throw = true): mixed

Return the latest value in the map

AbstractMap::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

AbstractMap::offsetExists

public function offsetExists(mixed $offset): bool

AbstractMap::offsetGet

public function offsetGet(mixed $offset): mixed

AbstractMap::offsetSet

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

AbstractMap::offsetUnset

public function offsetUnset(mixed $offset): void

AbstractMap::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Map to a single value using a callback function

Callback receive $accumulator,$value and $key

AbstractMap::removeKey

public function removeKey(mixed $searchedKey): static

Remove a value in the map by key

AbstractMap::removeValue

public function removeValue(mixed $searchedValue): static

Remove a value in the map by value

AbstractMap::set

public function set(mixed $newKey, mixed $newValue): static

Add or replace a value in the map

AbstractMap::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the map

AbstractMap::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable(TValue, TValue, TKey, TKey, int, int): int

and must return -1,0,1 as spaceship operator

AbstractMap::toArray

public function toArray(): array

Return an array representing the values

AbstractMap::valueDiff

public function valueDiff(AbstractMap $compared): static

Return a map of all items where values are not in arguments map

AbstractMap::valueIntersect

public function valueIntersect(AbstractMap $compared): static

Return a map of all items where values are in argument map

AbstractMap::values

public function values(): Generator

Return an iterator of values

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Micoli\Multitude

A collection library for PHP.

Build StatusCoverage StatusLatest Stable VersionTotal DownloadsLatest Unstable VersionLicensePHP Version Require

Two types of collections are available:

  • Sets (MutableSet and ImmutableSet), are sequences of unique values. Values can be of any types.
  • Map (MutableMap and ImmutableMap), is a sequential collection of key-value pairs. Keys can be any type, but must be unique. Values can be of any types.

In both ImmutableSet and ImmutableMap, if a method alter the content af the inner values, a new instance is returned of the same type. Oppositely, in MutableSet and MutableMap, same methods are altering the inner values.

Methods are the most possible fluent.

Thanks to https://github.com/BenMorel for the main ideas used in that library, this is a complete rewrite of it's initial version.

Installation

This library is installable via Composer:

composer require micoli/multitude

Requirements

This library requires PHP 8.0 or later.

Project status

While this library is still under development, it is still in early development status. It follows semver version tagging.

Quick start

Constructor are only statics:

  • new MutableSet(['a','b','c'])
  • new MutableMap([2=>'a',3=>'b',4=>'c'])
  • new MutableMap([[2,'a'],['2','aa'],[3,'b'],['3','bb'],[4,'c'])

You can use fromTuples constructor if you need a strong typing for keys of your map, e.g. '2' key is different of 2.

Methods that accept a bool $throw parameter will trigger an exception if $throw == true or fails silently if $throw == false.

Example with an associative array

publicfunctiontestItShouldFullyWorkWithAssociativeArray(): void
{
/** @var ImmutableMap<string, array{value:int,tags:list<string>}> $map */$map = newImmutableMap([
['library', ['value' => 10, 'tags' => ['tag1']]],
['projects', ['value' => 5, 'tags' => ['tag2']]],
['gist', ['value' => 7, 'tags' => ['tag1', 'tag2']]],
['repository', ['value' => 7, 'tags' => ['tag3']]],
]);
$totalSum = $map
->filter(fn (array$project, mixed$category): bool => array_search('tag1', $project['tags']) !== false)
->reduce(fn (int$sum, mixed$project, mixed$category): int => $sum + $project['value'], 0);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
}

Example with an immutable map fully typed

File: Project.php

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
class Project
{
publicfunction__construct(
publicreadonlyint$value,
publicreadonlyTags$tags,
) {
}
}

File: Tags

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Set\ImmutableSet;
/** * @extends ImmutableSet<string> */class Tags extends ImmutableSet
{
}

File: Projects

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Map\ImmutableMap;
/** * @extends ImmutableMap<string, Project> */class Projects extends ImmutableMap
{
/** * Add or replace a value in the map */publicfunctionimprovedSet(string$newKey, Project$newValue): static
{
// do specific stuff, like logging or therreturn$this->set($newKey, $newValue);
}
}
publicfunctiontestItShouldFullyWorkWithObjects(): void
{
$map = newProjects([
['library', newProject(10, newTags(['tag1']))],
['projects', newProject(5, newTags(['tag2']))],
['gist', newProject(7, newTags(['tag1', 'tag2']))],
['repository', newProject(7, newTags(['tag3']))],
]);
$totalSum = $map
->filter(fn (Project$project, mixed$category): bool => $project->tags->hasValue('tag1'))
->reduce(fn (int$sum, Project$project, mixed$category): int => $sum + $project->value, 0);
self::assertInstanceOf(
Projects::class,
$map->filter(fn (Project$project, mixed$category): bool => true),
);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
$newMap = $map->improvedSet('NewType', newProject(10, newTags(['tag4'])));
self::assertCount(5, $newMap);
}

Available verbs

Verb parity

ImmutableMapMutableMapImmutableSetMutableSet
__construct[x][x][x][x]
append[x][x]
apply[x][x][x][x]
count[x][x][x][x]
filter[x][x][x][x]
first[x][x][x][x]
forEach[x][x][x][x]
fromIterable[x][x]
get[x][x][x][x]
getIterator[x][x][x][x]
getTuples[x][x]
hasIndex[x][x]
hasKey[x][x]
hasValue[x][x][x][x]
indexDiff[x][x]
indexIntersect[x][x]
isEmpty[x][x][x][x]
keyDiff[x][x]
keyIntersect[x][x]
keys[x][x][x][x]
ImmutableMapMutableMapImmutableSetMutableSet
last[x][x][x][x]
map[x][x][x][x]
offsetExists[x][x]
offsetGet[x][x]
offsetSet[x][x]
offsetUnset[x][x]
reduce[x][x][x][x]
remove[x][x]
removeKey[x][x]
removeValue[x][x]
set[x][x]
slice[x][x][x][x]
sort[x][x][x][x]
toArray[x][x][x][x]
toImmutable[x][x]
toMutable[x][x]
valueDiff[x][x][x][x]
valueIntersect[x][x][x][x]
values[x][x][x][x]

AbstractSet

AbstractMap

AbstractSet

AbstractSet::__construct

public function __construct(iterable $values = [])

AbstractSet::append

public function append(mixed $newValue, bool $throw = true): static

Append a value at the end of the set

AbstractSet::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractSet::count

public function count(): int

return the number of items in the set

AbstractSet::filter

public function filter(callable $callable): static

Filter the set using a callback function

AbstractSet::first

public function first(bool $throw = true): mixed

Return the first value in the set

AbstractSet::forEach

public function forEach(callable $callable): static

Apply a callback on set values

Callback receive $value and $index

AbstractSet::get

public function get(int $index, mixed $defaultValue = null): mixed

Return a value in the set by index

AbstractSet::getIterator

public function getIterator(): Traversable

Return an iterator for values

AbstractSet::hasIndex

public function hasIndex(int $index): bool

Return if a set contains an index

AbstractSet::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a set contains a value

AbstractSet::indexDiff

public function indexDiff(AbstractSet $compared): static

Return a set of all items where keys are not in argument set

AbstractSet::indexIntersect

public function indexIntersect(AbstractSet $compared): static

Return a map of all items where keys are in arguments map

AbstractSet::isEmpty

public function isEmpty(): bool

Return if a set is empty

AbstractSet::keys

public function keys(): Generator

Return an iterator of keys

AbstractSet::last

public function last(bool $throw = true): mixed

Return the latest value in the set

AbstractSet::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

Callback receive $value and $index

AbstractSet::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Set to a single value using a callback function

Callback receive $accumulator,$value and $index

AbstractSet::remove

public function remove(mixed $searchedValue, bool $throw = true): static

Remove a value in the set

AbstractSet::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the set

AbstractSet::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable (TValue, TValue, int, int): int

and must return -1,0,1 as spaceship operator

AbstractSet::toArray

public function toArray(): array

Return an array representing the values

AbstractSet::valueDiff

public function valueDiff(AbstractSet $compared): static

Return a Set of all items where values are not in argument set

AbstractSet::valueIntersect

public function valueIntersect(AbstractSet $compared): static

Return a set of all items where values are in argument set

AbstractSet::values

public function values(): Generator

Return an iterator of values

AbstractMap

AbstractMap::__construct

public function __construct(array $tuples = [])

AbstractMap::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractMap::count

public function count(): int

Return the number of items in the map

AbstractMap::filter

public function filter(callable $callable): static

Filter the map using a callback function

AbstractMap::first

public function first(bool $throw = true): mixed

Return the first value in the map

AbstractMap::forEach

public function forEach(callable $callable): static

Apply a callback on set values

AbstractMap::fromIterable

public static function fromIterable(iterable $values): static

Return a new instance from an array.

AbstractMap::get

public function get(mixed $searchedKey, mixed $defaultValue = null): mixed

Return a value in the map by index

AbstractMap::getIterator

public function getIterator(): Traversable

Return an iterator for values by keys

AbstractMap::getTuples

public function getTuples(): array

AbstractMap::hasKey

public function hasKey(mixed $searchedKey): bool

Return if a map contains a specific key

AbstractMap::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a map contains a specific value

AbstractMap::isEmpty

public function isEmpty(): bool

Return if a map is empty

AbstractMap::keyDiff

public function keyDiff(AbstractMap $compared): static

Return a map of all items where keys are not in argument map

AbstractMap::keyIntersect

public function keyIntersect(AbstractMap $compared): static

Return a map of all items where keys are in arguments map

AbstractMap::keys

public function keys(): Generator

Return an iterator of keys

AbstractMap::last

public function last(bool $throw = true): mixed

Return the latest value in the map

AbstractMap::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

AbstractMap::offsetExists

public function offsetExists(mixed $offset): bool

AbstractMap::offsetGet

public function offsetGet(mixed $offset): mixed

AbstractMap::offsetSet

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

AbstractMap::offsetUnset

public function offsetUnset(mixed $offset): void

AbstractMap::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Map to a single value using a callback function

Callback receive $accumulator,$value and $key

AbstractMap::removeKey

public function removeKey(mixed $searchedKey): static

Remove a value in the map by key

AbstractMap::removeValue

public function removeValue(mixed $searchedValue): static

Remove a value in the map by value

AbstractMap::set

public function set(mixed $newKey, mixed $newValue): static

Add or replace a value in the map

AbstractMap::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the map

AbstractMap::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable(TValue, TValue, TKey, TKey, int, int): int

and must return -1,0,1 as spaceship operator

AbstractMap::toArray

public function toArray(): array

Return an array representing the values

AbstractMap::valueDiff

public function valueDiff(AbstractMap $compared): static

Return a map of all items where values are not in arguments map

AbstractMap::valueIntersect

public function valueIntersect(AbstractMap $compared): static

Return a map of all items where values are in argument map

AbstractMap::values

public function values(): Generator

Return an iterator of values

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Micoli\Multitude

A collection library for PHP.

Build StatusCoverage StatusLatest Stable VersionTotal DownloadsLatest Unstable VersionLicensePHP Version Require

Two types of collections are available:

  • Sets (MutableSet and ImmutableSet), are sequences of unique values. Values can be of any types.
  • Map (MutableMap and ImmutableMap), is a sequential collection of key-value pairs. Keys can be any type, but must be unique. Values can be of any types.

In both ImmutableSet and ImmutableMap, if a method alter the content af the inner values, a new instance is returned of the same type. Oppositely, in MutableSet and MutableMap, same methods are altering the inner values.

Methods are the most possible fluent.

Thanks to https://github.com/BenMorel for the main ideas used in that library, this is a complete rewrite of it's initial version.

Installation

This library is installable via Composer:

composer require micoli/multitude

Requirements

This library requires PHP 8.0 or later.

Project status

While this library is still under development, it is still in early development status. It follows semver version tagging.

Quick start

Constructor are only statics:

  • new MutableSet(['a','b','c'])
  • new MutableMap([2=>'a',3=>'b',4=>'c'])
  • new MutableMap([[2,'a'],['2','aa'],[3,'b'],['3','bb'],[4,'c'])

You can use fromTuples constructor if you need a strong typing for keys of your map, e.g. '2' key is different of 2.

Methods that accept a bool $throw parameter will trigger an exception if $throw == true or fails silently if $throw == false.

Example with an associative array

publicfunctiontestItShouldFullyWorkWithAssociativeArray(): void
{
/** @var ImmutableMap<string, array{value:int,tags:list<string>}> $map */$map = newImmutableMap([
['library', ['value' => 10, 'tags' => ['tag1']]],
['projects', ['value' => 5, 'tags' => ['tag2']]],
['gist', ['value' => 7, 'tags' => ['tag1', 'tag2']]],
['repository', ['value' => 7, 'tags' => ['tag3']]],
]);
$totalSum = $map
->filter(fn (array$project, mixed$category): bool => array_search('tag1', $project['tags']) !== false)
->reduce(fn (int$sum, mixed$project, mixed$category): int => $sum + $project['value'], 0);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
}

Example with an immutable map fully typed

File: Project.php

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
class Project
{
publicfunction__construct(
publicreadonlyint$value,
publicreadonlyTags$tags,
) {
}
}

File: Tags

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Set\ImmutableSet;
/** * @extends ImmutableSet<string> */class Tags extends ImmutableSet
{
}

File: Projects

<?phpdeclare(strict_types=1);
namespaceMicoli\Multitude\Tests\Fixtures;
useMicoli\Multitude\Map\ImmutableMap;
/** * @extends ImmutableMap<string, Project> */class Projects extends ImmutableMap
{
/** * Add or replace a value in the map */publicfunctionimprovedSet(string$newKey, Project$newValue): static
{
// do specific stuff, like logging or therreturn$this->set($newKey, $newValue);
}
}
publicfunctiontestItShouldFullyWorkWithObjects(): void
{
$map = newProjects([
['library', newProject(10, newTags(['tag1']))],
['projects', newProject(5, newTags(['tag2']))],
['gist', newProject(7, newTags(['tag1', 'tag2']))],
['repository', newProject(7, newTags(['tag3']))],
]);
$totalSum = $map
->filter(fn (Project$project, mixed$category): bool => $project->tags->hasValue('tag1'))
->reduce(fn (int$sum, Project$project, mixed$category): int => $sum + $project->value, 0);
self::assertInstanceOf(
Projects::class,
$map->filter(fn (Project$project, mixed$category): bool => true),
);
self::assertSame($totalSum, 17);
self::assertCount(4, $map);
$newMap = $map->improvedSet('NewType', newProject(10, newTags(['tag4'])));
self::assertCount(5, $newMap);
}

Available verbs

Verb parity

ImmutableMapMutableMapImmutableSetMutableSet
__construct[x][x][x][x]
append[x][x]
apply[x][x][x][x]
count[x][x][x][x]
filter[x][x][x][x]
first[x][x][x][x]
forEach[x][x][x][x]
fromIterable[x][x]
get[x][x][x][x]
getIterator[x][x][x][x]
getTuples[x][x]
hasIndex[x][x]
hasKey[x][x]
hasValue[x][x][x][x]
indexDiff[x][x]
indexIntersect[x][x]
isEmpty[x][x][x][x]
keyDiff[x][x]
keyIntersect[x][x]
keys[x][x][x][x]
ImmutableMapMutableMapImmutableSetMutableSet
last[x][x][x][x]
map[x][x][x][x]
offsetExists[x][x]
offsetGet[x][x]
offsetSet[x][x]
offsetUnset[x][x]
reduce[x][x][x][x]
remove[x][x]
removeKey[x][x]
removeValue[x][x]
set[x][x]
slice[x][x][x][x]
sort[x][x][x][x]
toArray[x][x][x][x]
toImmutable[x][x]
toMutable[x][x]
valueDiff[x][x][x][x]
valueIntersect[x][x][x][x]
values[x][x][x][x]

AbstractSet

AbstractMap

AbstractSet

AbstractSet::__construct

public function __construct(iterable $values = [])

AbstractSet::append

public function append(mixed $newValue, bool $throw = true): static

Append a value at the end of the set

AbstractSet::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractSet::count

public function count(): int

return the number of items in the set

AbstractSet::filter

public function filter(callable $callable): static

Filter the set using a callback function

AbstractSet::first

public function first(bool $throw = true): mixed

Return the first value in the set

AbstractSet::forEach

public function forEach(callable $callable): static

Apply a callback on set values

Callback receive $value and $index

AbstractSet::get

public function get(int $index, mixed $defaultValue = null): mixed

Return a value in the set by index

AbstractSet::getIterator

public function getIterator(): Traversable

Return an iterator for values

AbstractSet::hasIndex

public function hasIndex(int $index): bool

Return if a set contains an index

AbstractSet::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a set contains a value

AbstractSet::indexDiff

public function indexDiff(AbstractSet $compared): static

Return a set of all items where keys are not in argument set

AbstractSet::indexIntersect

public function indexIntersect(AbstractSet $compared): static

Return a map of all items where keys are in arguments map

AbstractSet::isEmpty

public function isEmpty(): bool

Return if a set is empty

AbstractSet::keys

public function keys(): Generator

Return an iterator of keys

AbstractSet::last

public function last(bool $throw = true): mixed

Return the latest value in the set

AbstractSet::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

Callback receive $value and $index

AbstractSet::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Set to a single value using a callback function

Callback receive $accumulator,$value and $index

AbstractSet::remove

public function remove(mixed $searchedValue, bool $throw = true): static

Remove a value in the set

AbstractSet::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the set

AbstractSet::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable (TValue, TValue, int, int): int

and must return -1,0,1 as spaceship operator

AbstractSet::toArray

public function toArray(): array

Return an array representing the values

AbstractSet::valueDiff

public function valueDiff(AbstractSet $compared): static

Return a Set of all items where values are not in argument set

AbstractSet::valueIntersect

public function valueIntersect(AbstractSet $compared): static

Return a set of all items where values are in argument set

AbstractSet::values

public function values(): Generator

Return an iterator of values

AbstractMap

AbstractMap::__construct

public function __construct(array $tuples = [])

AbstractMap::apply

public function apply(callable $callable): static

Replace all values by applying a callback to the current instance

AbstractMap::count

public function count(): int

Return the number of items in the map

AbstractMap::filter

public function filter(callable $callable): static

Filter the map using a callback function

AbstractMap::first

public function first(bool $throw = true): mixed

Return the first value in the map

AbstractMap::forEach

public function forEach(callable $callable): static

Apply a callback on set values

AbstractMap::fromIterable

public static function fromIterable(iterable $values): static

Return a new instance from an array.

AbstractMap::get

public function get(mixed $searchedKey, mixed $defaultValue = null): mixed

Return a value in the map by index

AbstractMap::getIterator

public function getIterator(): Traversable

Return an iterator for values by keys

AbstractMap::getTuples

public function getTuples(): array

AbstractMap::hasKey

public function hasKey(mixed $searchedKey): bool

Return if a map contains a specific key

AbstractMap::hasValue

public function hasValue(mixed $searchedValue): bool

Return if a map contains a specific value

AbstractMap::isEmpty

public function isEmpty(): bool

Return if a map is empty

AbstractMap::keyDiff

public function keyDiff(AbstractMap $compared): static

Return a map of all items where keys are not in argument map

AbstractMap::keyIntersect

public function keyIntersect(AbstractMap $compared): static

Return a map of all items where keys are in arguments map

AbstractMap::keys

public function keys(): Generator

Return an iterator of keys

AbstractMap::last

public function last(bool $throw = true): mixed

Return the latest value in the map

AbstractMap::map

public function map(callable $callable)

Applies the callback to the values, keys are preserved

AbstractMap::offsetExists

public function offsetExists(mixed $offset): bool

AbstractMap::offsetGet

public function offsetGet(mixed $offset): mixed

AbstractMap::offsetSet

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

AbstractMap::offsetUnset

public function offsetUnset(mixed $offset): void

AbstractMap::reduce

public function reduce(callable $callable, mixed $accumulator): mixed

Iteratively reduce the Map to a single value using a callback function

Callback receive $accumulator,$value and $key

AbstractMap::removeKey

public function removeKey(mixed $searchedKey): static

Remove a value in the map by key

AbstractMap::removeValue

public function removeValue(mixed $searchedValue): static

Remove a value in the map by value

AbstractMap::set

public function set(mixed $newKey, mixed $newValue): static

Add or replace a value in the map

AbstractMap::slice

public function slice(int $offset, ?int $length = null): static

Extract a slice of the map

AbstractMap::sort

public function sort(callable $callable): static

Sort the map using a callback function

callback is of callable(TValue, TValue, TKey, TKey, int, int): int

and must return -1,0,1 as spaceship operator

AbstractMap::toArray

public function toArray(): array

Return an array representing the values

AbstractMap::valueDiff

public function valueDiff(AbstractMap $compared): static

Return a map of all items where values are not in arguments map

AbstractMap::valueIntersect

public function valueIntersect(AbstractMap $compared): static

Return a map of all items where values are in argument map

AbstractMap::values

public function values(): Generator

Return an iterator of values

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages