diff --git a/README.md b/README.md index 0fedeb8..57b2f44 100644 --- a/README.md +++ b/README.md @@ -5093,10 +5093,10 @@ Map::from( ['a', 'b'] )->suffix( function( $item, $key ) { Returns the sum of all integer and float values in the map. ```php -public function sum( string $col = null ) : float +public function sum( $col = null ) : float ``` -* @param **string|null** `$col` Key in the nested array or object to sum up +* @param **Closure|string|null** `$col` Closure, key in the nested array or object to sum up * @return **float** Sum of all elements or 0 if there are no elements in the map This does also work to map values from multi-dimensional arrays by passing the keys @@ -5118,6 +5118,9 @@ Map::from( [['p' => 30], ['p' => 50], ['p' => 10]] )->sum( 'p' ); Map::from( [['i' => ['p' => 30]], ['i' => ['p' => 50]]] )->sum( 'i/p' ); // 80 + +Map::from( [30, 50, 10] )->sum( fn( $val, $key ) => $val < 50 ? $val : 0 ); +// 40 ``` diff --git a/src/Map.php b/src/Map.php index 5557502..0edd29a 100644 --- a/src/Map.php +++ b/src/Map.php @@ -4658,10 +4658,11 @@ public function suffix( $suffix, int $depth = null ) : self * Map::from( [1, 'sum', 5] )->sum(); * Map::from( [['p' => 30], ['p' => 50], ['p' => 10]] )->sum( 'p' ); * Map::from( [['i' => ['p' => 30]], ['i' => ['p' => 50]]] )->sum( 'i/p' ); + * Map::from( [30, 50, 10] )->sum( fn( $val, $key ) => $val < 50 ? $val : 0 ); * * Results: * The first line will return "9", the second one "6", the third one "90" - * and the last one "80". + * the forth on "80" and the last one "40". * * NULL values are treated as 0, non-numeric values will generate an error. * @@ -4670,12 +4671,23 @@ public function suffix( $suffix, int $depth = null ) : self * to get "val" from ['key1' => ['key2' => ['key3' => 'val']]]. The same applies to * public properties of objects or objects implementing __isset() and __get() methods. * - * @param string|null $key Key or path to the values in the nested array or object to sum up + * @param Closure|string|null $col Closure, key or path to the values in the nested array or object to sum up * @return float Sum of all elements or 0 if there are no elements in the map */ - public function sum( string $key = null ) : float + public function sum( $col = null ) : float { - $vals = $key !== null ? $this->col( $key )->toArray() : $this->list(); + if( $col instanceof \Closure ) + { + $vals = []; + foreach( $this->list() as $key => $val ) { + $vals[] = $col( $val, $key ); + } + } + else + { + $vals = $col !== null ? $this->col( $col )->toArray() : $this->list(); + } + return !empty( $vals ) ? array_sum( $vals ) : 0; } diff --git a/tests/MapTest.php b/tests/MapTest.php index f85175a..94de956 100644 --- a/tests/MapTest.php +++ b/tests/MapTest.php @@ -3074,6 +3074,13 @@ public function testSum() } + public function testSumClosure() + { + $this->assertSame( 40.0, Map::from( [30, 50, 10] )->sum( fn( $val ) => $val < 50 ? $val : 0 ) ); + $this->assertSame( 60.0, Map::from( [30, 50, 10] )->sum( fn( $val, $key ) => $key > 0 ? $val : 0 ) ); + } + + public function testSumPath() { $this->assertSame( 90.0, Map::from( [['p' => 30], ['p' => 50], ['p' => 10]] )->sum( 'p' ) );