From a7ba395fe0750a4409443669d8200ad65aa894c8 Mon Sep 17 00:00:00 2001 From: Jan Machala Date: Wed, 23 Dec 2020 15:05:07 +0100 Subject: [PATCH] Support flatMap operation on Map --- src/Bonami/Collection/Map.php | 26 ++++++++++++++++++++++++++ tests/Bonami/Collection/MapTest.php | 12 ++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/Bonami/Collection/Map.php b/src/Bonami/Collection/Map.php index 600626d..83f6a63 100644 --- a/src/Bonami/Collection/Map.php +++ b/src/Bonami/Collection/Map.php @@ -878,6 +878,9 @@ public function __toString(): string * Constructs a list containing all elements after applying callback * on each value-key pair from Map * + * This operation does not follow functor laws, because it returns + * List instead of Map + * * Complexity: o(n) * * @see mapValues - for mapping just values and keeping Map as result @@ -896,4 +899,27 @@ public function map(callable $mapper): ArrayList return ArrayList::fromIterable($mapped); } + + /** + * Constructs a list containing all elements after applying callback + * on each value-key pair from Map and then flattening it. + * + * This operation does not follow monad laws, because it returns + * List instead of Map + * + * Complexity: o(n) + * + * @phpstan-template B + * + * @phpstan-param callable(V, K): iterable $mapper + * + * @phpstan-return ArrayList + */ + public function flatMap(callable $mapper): ArrayList + { + /** @phpstan-var ArrayList */ + $flattened = $this->map($mapper)->flatten(); + + return $flattened; + } } diff --git a/tests/Bonami/Collection/MapTest.php b/tests/Bonami/Collection/MapTest.php index c836f2f..88707ee 100644 --- a/tests/Bonami/Collection/MapTest.php +++ b/tests/Bonami/Collection/MapTest.php @@ -76,6 +76,18 @@ public function testMap(): void self::assertEquals(ArrayList::fromIterable(["a:1", "b:2"]), $mapped); } + public function testFlatMap(): void + { + $map = new Map([ + [1, "a"], + [2, "b"], + ]); + $mapped = $map->flatMap(static function (string $value, int $key): Option { + return $key % 2 === 0 ? Option::some("$value:$key") : Option::none(); + }); + self::assertEquals(ArrayList::fromIterable(["b:2"]), $mapped); + } + public function testMapKeys(): void { $map = new Map([