Skip to content

Commit 4bf1f33

Browse files
committed
Allow key/path as argument for countBy()
1 parent 1f37846 commit 4bf1f33

File tree

2 files changed

+25
-10
lines changed

2 files changed

+25
-10
lines changed

src/Map.php

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,30 +1144,37 @@ public function count() : int
11441144
* Examples:
11451145
* Map::from( [1, 'foo', 2, 'foo', 1] )->countBy();
11461146
* Map::from( [1.11, 3.33, 3.33, 9.99] )->countBy();
1147+
* Map::from( [['i' => ['p' => 1.11]], ['i' => ['p' => 3.33]], ['i' => ['p' => 3.33]]] )->countBy( 'i/p' );
11471148
* Map::from( ['[email protected]', '[email protected]', '[email protected]'] )->countBy( function( $email ) {
11481149
* return substr( strrchr( $email, '@' ), 1 );
11491150
* } );
11501151
*
11511152
* Results:
11521153
* [1 => 2, 'foo' => 2, 2 => 1]
11531154
* ['1.11' => 1, '3.33' => 2, '9.99' => 1]
1155+
* ['1.11' => 1, '3.33' => 2]
11541156
* ['gmail.com' => 2, 'yahoo.com' => 1]
11551157
*
11561158
* Counting values does only work for integers and strings because these are
11571159
* the only types allowed as array keys. All elements are casted to strings
11581160
* if no callback is passed. Custom callbacks need to make sure that only
11591161
* string or integer values are returned!
11601162
*
1161-
* @param callable|null $callback Function with (value, key) parameters which returns the value to use for counting
1163+
* @param \Closure|string|null $col Key as "key1/key2/key3" or function with (value, key) parameters returning the values for counting
11621164
* @return self<int|string,mixed> New map with values as keys and their count as value
11631165
*/
1164-
public function countBy( ?callable $callback = null ) : self
1166+
public function countBy( $col = null ) : self
11651167
{
1166-
$callback = $callback ?: function( $value ) {
1167-
return (string) $value;
1168-
};
1168+
if( !( $col instanceof \Closure ) )
1169+
{
1170+
$parts = $col ? explode( $this->sep, (string) $col ) : [];
1171+
1172+
$col = function( $item ) use ( $parts ) {
1173+
return (string) $this->val( $item, $parts );
1174+
};
1175+
}
11691176

1170-
return new static( array_count_values( array_map( $callback, $this->list() ) ) );
1177+
return new static( array_count_values( array_map( $col, $this->list() ) ) );
11711178
}
11721179

11731180

@@ -6140,17 +6147,16 @@ protected function &list() : array
61406147
* @param \Closure|string|null $key Closure or key (e.g. "key1/key2/key3") to retrieve the value for
61416148
* @return \Closure Closure that retrieves the value for the passed key
61426149
*/
6143-
protected function mapper( $key = null, bool $cast = false ) : \Closure
6150+
protected function mapper( $key = null ) : \Closure
61446151
{
61456152
if( $key instanceof \Closure ) {
61466153
return $key;
61476154
}
61486155

61496156
$parts = $key ? explode( $this->sep, (string) $key ) : [];
61506157

6151-
return function( $item ) use ( $cast, $parts ) {
6152-
$val = $this->val( $item, $parts );
6153-
return $cast ? (string) $val : $val;
6158+
return function( $item ) use ( $parts ) {
6159+
return $this->val( $item, $parts );
61546160
};
61556161
}
61566162

tests/MapTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,15 @@ public function testCountBy()
564564
}
565565

566566

567+
public function testCountByPath()
568+
{
569+
$r = Map::from( [['i' => ['p' => 1.11]], ['i' => ['p' => 3.33]], ['i' => ['p' => 3.33]]] )->countBy( 'i/p' );
570+
571+
$this->assertInstanceOf( Map::class, $r );
572+
$this->assertSame( ['1.11' => 1, '3.33' => 2], $r->toArray() );
573+
}
574+
575+
567576
public function testCountByCallback()
568577
{
569578
$r = Map::from( ['[email protected]', '[email protected]', '[email protected]'] )->countBy( function( $email ) {

0 commit comments

Comments
 (0)