jgdoncel
11/18/2016 - 11:46 AM

PHP : Groups an array by a given key

PHP : Groups an array by a given key

{
  "name": "jgdoncel/php-array-group-by",
  "description": "Groups an array by a given key.",
  "authors": [
    {
      "name": "Jose García",
      "email": "jgdoncel@gmail.com",
      "homepage": "https://github.com/jgdoncel"
    }
  ],
  "keywords": [
    "function"
  ],
  "require": {
    "php": ">=5.3.3"
  },
  "autoload": {
    "files": ["Function.Array-Group-By.php"]
  }
}

Fork of https://gist.github.com/mcaskill/baaee44487653e1afc0d with no short sintax for arrays allowing PHP < 5.4

array_group_by

(PHP 5 >= 5.3.3)
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 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
{
    "repositories": [
        {
          "type": "git",
          "url": "https://gist.github.com/***.git"
        }
    ],
    "require": {
        "jgdoncel/php-array-group-by": "dev-master"
    }
}

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.

<?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.
	 *
	 *                       ```
	 *                       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_callable( $key ) ? $key : null );
		$_key = $key;

		// Load the new array, splitting by the target key
		$grouped = array();
		foreach ( $array as $value ) {
			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 ];
			} else {
				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( array( $value ), array_slice( $args, 2, func_num_args() ) );
				$grouped[ $key ] = call_user_func_array( 'array_group_by', $params );
			}
		}

		return $grouped;
	}

endif;