Browse Source

added ArrayHelper::multimap

Fabian Peter Hammerle 7 years ago
parent
commit
7b9a845e5c
2 changed files with 107 additions and 0 deletions
  1. 25 0
      ArrayHelper.php
  2. 82 0
      tests/ArrayHelperTest.php

+ 25 - 0
ArrayHelper.php

@@ -14,4 +14,29 @@ class ArrayHelper
             false
             );
     }
+
+    /**
+     * @param array $source_array
+     * @param \Closure $callback
+     * @return array
+     */
+   public static function multimap(array $source_array, \Closure $callback)
+   {
+       $mapped_array = [];
+       foreach($source_array as $old_key => $old_value) {
+           $pairs = $callback($old_key, $old_value);
+           if($pairs === null) {
+               // skipp
+           } elseif(is_array($pairs)) {
+               foreach($pairs as $new_key => $new_pair) {
+                   $mapped_array[$new_key] = $new_pair;
+               }
+           } else {
+               throw new \UnexpectedValueException(
+                    sprintf('expected array, %s given', gettype($pairs))
+                    );
+           }
+       }
+       return $mapped_array;
+   }
 }

+ 82 - 0
tests/ArrayHelperTest.php

@@ -91,4 +91,86 @@ class ArrayHelperTest extends \PHPUnit_Framework_TestCase
                 ])
             );
     }
+
+    public function multimapProvider()
+    {
+        return [
+            [
+                ['a' => 1, 'b' => 2, 'c' => 3],
+                function($k, $v) { return [$k => $v]; },
+                ['a' => 1, 'b' => 2, 'c' => 3],
+                ],
+            [
+                ['a' => 1, 'b' => 2, 'c' => 3],
+                function($k, $v) { return [$v => $k]; },
+                [1 => 'a', 2 => 'b', 3 => 'c'],
+                ],
+            [
+                ['a' => 1, 'b' => 2, 'c' => 3],
+                function($k, $v) { return [strtoupper($k) => $v * $v]; },
+                ['A' => 1, 'B' => 4, 'C' => 9],
+                ],
+            [
+                ['a' => 1, 'b' => 2, 'c' => 3],
+                function($k, $v) { return [$k => null]; },
+                ['a' => null, 'b' => null, 'c' => null],
+                ],
+            [
+                ['a' => 1, 'b' => 2, 'b' => 3],
+                function($k, $v) { return [$k => $v]; },
+                ['a' => 1, 'b' => 3],
+                ],
+            [
+                ['a' => 1, 'b' => 2, 'c' => 3],
+                function($k, $v) { return ($v % 2) ? [$k => $v * $v] : null; },
+                ['a' => 1, 'c' => 9],
+                ],
+            [
+                ['a' => 1, 'b' => 2, 'c' => 3],
+                function($k, $v) { return ($v % 2) ? [$k => $v * $v] : []; },
+                ['a' => 1, 'c' => 9],
+                ],
+            [
+                ['a' => 1, 'b' => 2, 'c' => 3],
+                function($k, $v) { return [$k => $v, $k.'^2' => $v * $v]; },
+                ['a' => 1, 'a^2' => 1, 'b' => 2, 'b^2' => 4, 'c' => 3, 'c^2' => 9],
+                ],
+            [
+                ['a' => 1, 'b' => 2, 'c' => 3],
+                function($k, $v) { return [$k => [[$v]], strtoupper($k) => []]; },
+                ['a' => [[1]], 'A' => [], 'b' => [[2]], 'B' => [], 'c' => [[3]], 'C' => []],
+                ],
+            ];
+    }
+
+    /**
+     * @dataProvider multimapProvider
+     */
+    public function testMultimap($source, $callback, $expected)
+    {
+        $this->assertSame($expected, ArrayHelper::multimap($source, $callback));
+    }
+
+    public function multimapUnexpectedValueProvider()
+    {
+        return [
+            [
+                ['a' => 1, 'b' => 2, 'c' => 3],
+                function($k, $v) { return $v; },
+                ],
+            [
+                ['a' => 1, 'b' => 2, 'c' => 3],
+                function($k, $v) { return 'string'; },
+                ],
+            ];
+    }
+
+    /**
+     * @dataProvider multimapUnexpectedValueProvider
+     * @expectedException \UnexpectedValueException
+     */
+    public function testMultimapUnexpectedValue($source, $callback)
+    {
+        ArrayHelper::multimap($source, $callback);
+    }
 }