Skip to content

Instantly share code, notes, and snippets.

@ioanszabo
Forked from mcaskill/Function.Array-Group-By.php
Last active June 16, 2018 15:35
Show Gist options
  • Save ioanszabo/8f944cfb0edad5f90fcf1e8a3b34b85c to your computer and use it in GitHub Desktop.
Save ioanszabo/8f944cfb0edad5f90fcf1e8a3b34b85c to your computer and use it in GitHub Desktop.
PHP : Groups an array by a given key

array_group_by

(PHP 5 >= 5.4)
array_group_by — Groups an array by a given key.

Description

array|null array_group_by( array $array, mixed $key1 [, mixed $... ] )

Groups an array into arrays by a given $key, or set of keys, shared between all array members.

Based on Jake Zatecky's array_group_by() function.

This fork offers:

  • $key parameter can be a closure

Parameters

  • $array — The array to have grouping performed on.

  • $key — The key to group or split by. Can be a string, an integer, a float, or a callback. If the key is NULL, the iterated element is skipped. If the key is a callback, it must return a valid key from the array.

    string|int callback ( mixed $item )

  • ... — Additional keys for grouping the next set of sub-arrays.

Return Values

Returns a multidimensional array, with each dimension containing elements grouped by the passed key(s).

Errors/Exceptions

If $key is not one of the accepted types E_USER_ERROR will be thrown and NULL returned.

Examples

Example #1 array_group_by() example

$records = [
	[
		"state"  => "IN",
		"city"   => "Indianapolis",
		"object" => "School bus"
	],
	[
		"state"  => "IN",
		"city"   => "Indianapolis",
		"object" => "Manhole"
	],
	[
		"state"  => "IN",
		"city"   => "Plainfield",
		"object" => "Basketball"
	],
	[
		"state"  => "CA",
		"city"   => "San Diego",
		"object" => "Light bulb"
	],
	[
		"state"  => "CA",
		"city"   => "Mountain View",
		"object" => "Space pen"
	]
];

$grouped = array_group_by( $records, "state", "city" );

The above example will output:

Array
(
	[IN] => Array
		(
			[Indianapolis] => Array
				(
					[0] => Array
						(
							[state] => IN
							[city] => Indianapolis
							[object] => School bus
						)

					[1] => Array
						(
							[state] => IN
							[city] => Indianapolis
							[object] => Manhole
						)

				)

			[Plainfield] => Array
				(
					[0] => Array
						(
							[state] => IN
							[city] => Plainfield
							[object] => Basketball
						)

				)

		)

	[CA] => Array
		(
			[San Diego] => Array
				(
					[0] => Array
						(
							[state] => CA
							[city] => San Diego
							[object] => Light bulb
						)

				)

			[Mountain View] => Array
				(
					[0] => Array
						(
							[state] => CA
							[city] => Mountain View
							[object] => Space pen
						)

				)

		)
)

Installation

With Composer

$ composer require mcaskill/php-array-group-by

Without Composer

Why are you not using composer? Download Function.Array-Group-By.php from the gist and save the file into your project path somewhere.

Tests

Run bin/phpunit into project home to run tests.

\.idea/
vendor/
<?php
use PHPUnit\Framework\TestCase;
/**
* Created by PhpStorm.
* User: szabo
* Date: 16.06.2018
* Time: 17:03
*/
class ArrayGroupByOnKeyTest extends TestCase {
private $sample = [
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "School bus"
],
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "Manhole"
],
[
"state" => "IN",
"city" => "Plainfield",
"object" => "Basketball"
],
[
"state" => "CA",
"city" => "San Diego",
"object" => "Light bulb"
],
[
"state" => "CA",
"city" => "Mountain View",
"object" => "Space pen"
]
];
/**
* @test
*/
public function groupByState() {
$expectedResult = [
"IN" => [
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "School bus"
],
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "Manhole"
],
[
"state" => "IN",
"city" => "Plainfield",
"object" => "Basketball"
],
],
"CA" => [
[
"state" => "CA",
"city" => "San Diego",
"object" => "Light bulb"
],
[
"state" => "CA",
"city" => "Mountain View",
"object" => "Space pen"
]
]
];
$this->assertEquals($expectedResult, array_group_by($this->sample, "state"));
}
/**
* @test
*/
public function groupByCity() {
$expectedResult = [
"Indianapolis" => [
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "School bus"
],
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "Manhole"
],
],
"Plainfield" => [
[
"state" => "IN",
"city" => "Plainfield",
"object" => "Basketball"
]
],
"San Diego" => [
[
"state" => "CA",
"city" => "San Diego",
"object" => "Light bulb"
]
],
"Mountain View" => [
[
"state" => "CA",
"city" => "Mountain View",
"object" => "Space pen"
]
]
];
$result = array_group_by($this->sample, "city");
$this->assertEquals($expectedResult, $result);
}
}
<?php
use PHPUnit\Framework\TestCase;
/**
* Created by PhpStorm.
* User: szabo
* Date: 16.06.2018
* Time: 17:03
*/
class ArrayGroupByOnKeyTest extends TestCase {
private $sample = [
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "School bus"
],
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "Manhole"
],
[
"state" => "IN",
"city" => "Plainfield",
"object" => "Basketball"
],
[
"state" => "CA",
"city" => "San Diego",
"object" => "Light bulb"
],
[
"state" => "CA",
"city" => "Mountain View",
"object" => "Space pen"
]
];
/**
* @test
*/
public function groupByState() {
$expectedResult = [
"IN" => [
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "School bus"
],
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "Manhole"
],
[
"state" => "IN",
"city" => "Plainfield",
"object" => "Basketball"
],
],
"CA" => [
[
"state" => "CA",
"city" => "San Diego",
"object" => "Light bulb"
],
[
"state" => "CA",
"city" => "Mountain View",
"object" => "Space pen"
]
]
];
$this->assertEquals($expectedResult, array_group_by($this->sample, "state"));
}
/**
* @test
*/
public function groupByCity() {
$expectedResult = [
"Indianapolis" => [
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "School bus"
],
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "Manhole"
],
],
"Plainfield" => [
[
"state" => "IN",
"city" => "Plainfield",
"object" => "Basketball"
]
],
"San Diego" => [
[
"state" => "CA",
"city" => "San Diego",
"object" => "Light bulb"
]
],
"Mountain View" => [
[
"state" => "CA",
"city" => "Mountain View",
"object" => "Space pen"
]
]
];
$result = array_group_by($this->sample, "city");
$this->assertEquals($expectedResult, $result);
}
}
<?php
use PHPUnit\Framework\TestCase;
class ArrayGroupByTwoKeysTest extends TestCase {
private $sample = [
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "School bus"
],
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "Manhole"
],
[
"state" => "IN",
"city" => "Plainfield",
"object" => "Basketball"
],
[
"state" => "CA",
"city" => "San Diego",
"object" => "Light bulb"
],
[
"state" => "CA",
"city" => "Mountain View",
"object" => "Space pen"
]
];
/**
* @test
*/
public function groupByStateAndCity() {
$expectedResult = [
'IN' => [
'Indianapolis' => [
[
'state' => 'IN',
'city' => 'Indianapolis',
'object' => 'School bus'
],
[
'state' => 'IN',
'city' => 'Indianapolis',
'object' => 'Manhole'
],
],
'Plainfield' => [
[
'state' => 'IN',
'city' => 'Plainfield',
'object' => 'Basketball'
]
]
],
'CA' => [
'San Diego' => [
[
'state' => 'CA',
'city' => 'San Diego',
'object' => 'Light bulb'
],
],
'Mountain View' => [
[
'state' => 'CA',
'city' => 'Mountain View',
'object' => 'Space pen'
]
]
]
];
$result = array_group_by($this->sample, 'state', 'city');
$this->assertEquals($expectedResult, $result);
}
}
<?php
use PHPUnit\Framework\TestCase;
class ArrayGroupByTwoKeysTest extends TestCase {
private $sample = [
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "School bus"
],
[
"state" => "IN",
"city" => "Indianapolis",
"object" => "Manhole"
],
[
"state" => "IN",
"city" => "Plainfield",
"object" => "Basketball"
],
[
"state" => "CA",
"city" => "San Diego",
"object" => "Light bulb"
],
[
"state" => "CA",
"city" => "Mountain View",
"object" => "Space pen"
]
];
/**
* @test
*/
public function groupByStateAndCity() {
$expectedResult = [
'IN' => [
'Indianapolis' => [
[
'state' => 'IN',
'city' => 'Indianapolis',
'object' => 'School bus'
],
[
'state' => 'IN',
'city' => 'Indianapolis',
'object' => 'Manhole'
],
],
'Plainfield' => [
[
'state' => 'IN',
'city' => 'Plainfield',
'object' => 'Basketball'
]
]
],
'CA' => [
'San Diego' => [
[
'state' => 'CA',
'city' => 'San Diego',
'object' => 'Light bulb'
],
],
'Mountain View' => [
[
'state' => 'CA',
'city' => 'Mountain View',
'object' => 'Space pen'
]
]
]
];
$result = array_group_by($this->sample, 'state', 'city');
$this->assertEquals($expectedResult, $result);
}
}
{
"name": "mcaskill/php-array-group-by",
"description": "Groups an array by a given key.",
"license": "MIT",
"version": "1.0.1",
"authors": [
{
"name": "Chauncey McAskill",
"email": "chauncey@mcaskill.ca",
"homepage": "https://github.com/mcaskill"
}
],
"keywords": [
"function"
],
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"require": {
"php": ">=5.4.0"
},
"autoload": {
"files": ["Function.Array-Group-By.php"]
},
"require-dev": {
"phpunit/phpunit": "^5"
}
}
<?php
if (!function_exists('array_group_by')) {
/**
* Groups an array by a given key.
*
* Groups an array into arrays by a given key, or set of keys, shared between all array members.
*
* Based on {@author Jake Zatecky}'s {@link https://github.com/jakezatecky/array_group_by array_group_by()} function.
* This variant allows $key to be closures.
*
* @param array $array The array to have grouping performed on.
* @param mixed $key,... The key to group or split by. Can be a _string_,
* an _integer_, a _float_, or a _callable_.
*
* If the key is a callback, it must return
* a valid key from the array.
*
* If the key is _NULL_, the iterated element is skipped.
*
* ```
* string|int callback ( mixed $item )
* ```
*
* @return array|null Returns a multidimensional array or `null` if `$key` is invalid.
*/
function array_group_by(array $array, $key)
{
if (!is_string($key) && !is_int($key) && !is_float($key) && !is_callable($key) ) {
trigger_error('array_group_by(): The key should be a string, an integer, or a callback', E_USER_ERROR);
return null;
}
$func = (!is_string($key) && is_callable($key) ? $key : null);
$_key = $key;
// Load the new array, splitting by the target key
$grouped = [];
foreach ($array as $value) {
$key = null;
if (is_callable($func)) {
$key = call_user_func($func, $value);
} elseif (is_object($value) && isset($value->{$_key})) {
$key = $value->{$_key};
} elseif (isset($value[$_key])) {
$key = $value[$_key];
}
if ($key === null) {
continue;
}
$grouped[$key][] = $value;
}
// Recursively build a nested grouping if more parameters are supplied
// Each grouped array value is grouped according to the next sequential key
if (func_num_args() > 2) {
$args = func_get_args();
foreach ($grouped as $key => $value) {
$params = array_merge([ $value ], array_slice($args, 2, func_num_args()));
$grouped[$key] = call_user_func_array('array_group_by', $params);
}
}
return $grouped;
}
}
vendor/phpunit/phpunit/phpunit --no-configuration ../array-group-by/Tests --colors="always"
vendor/phpunit/phpunit/phpunit --no-configuration ../array-group-by/Tests --colors="always"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment