Search code examples
phparraysmultidimensional-arraygrouping

Group a 2d array by a column and create subarrays in each group


I am trying to group an array by it's values. Below is my array:

$array = Array
(
    0 => Array
        (
            'name' => 'John Doe',
            'age' => '36',
            'code' => '437',                           
            'group' => '1000',
        ),
    1 => Array
        (
            'name' => 'John Doe',
            'age' => '36',
            'code' => '437',                           
            'group' => '7777',
        ),

    2 => Array
        (
            'name' => 'John Doe',
            'age' => '36',
            'code' => '437',                           
            'group' => '7777',
        ),
    3 => Array
        (
            'name' => 'John Doe',
            'age' => '36',
            'code' => '437',                           
            'group' => '4000',
        ),

    4 => Array
        (
            'name' => 'John Doe',
            'age' => '36',
            'code' => '437',                           
            'group' => '4000',
        ),

    5 => Array
        (
            'name' => 'John Doe',
            'age' => '36',
            'code' => '437',                           
            'group' => '5000',
        ),

    6 => Array
        (
            'name' => 'John Doe',
            'age' => '36',
            'code' => '437',                           
            'group' => '6000',
        ),

    7 => Array
        (
            'name' => 'John Doe',
            'age' => '36',
            'code' => '437',                           
            'group' => '6000',
        ),
);

I have tried below:

$result = array();
    foreach ($array as $key => $record) {
        if (!isset($result[$record['code']])) {
            $result[$record['code']] = array(
                'name' => $record['name'],
                'age' => $record['age'],
                'groups' => array(array($record['code'], $record['group'])),
            );
        }
        else {
            $result[$record['code']]['groups'][] = array($record['code'],$record['group']);
        }
    }
    $result = array_values($result);

    print_r($result);

And I am getting:

Array
(
    [0] => Array
        (
            [name] => John Doe
            [age] => 36
            [groups] => Array
                (
                    [0] => Array
                        (
                            [0] => 437
                            [1] => 1000
                        )

                    [1] => Array
                        (
                            [0] => 437
                            [1] => 7777
                        )

                    [2] => Array
                        (
                            [0] => 437
                            [1] => 7777
                        )

                    [3] => Array
                        (
                            [0] => 437
                            [1] => 4000
                        )

                    [4] => Array
                        (
                            [0] => 437
                            [1] => 4000
                        )

                    [5] => Array
                        (
                            [0] => 437
                            [1] => 5000
                        )

                    [6] => Array
                        (
                            [0] => 437
                            [1] => 6000
                        )

                    [7] => Array
                        (
                            [0] => 437
                            [1] => 6000
                        )

                )

        )

)

Now, I want my array to be grouped by the values of group 7777, 1000 and others(all others group values):

Array
(
    [0] => Array
        (
            [name] => John Doe
            [age] => 36
            [7777] => Array
                (
                    [0] => Array
                        (
                            [0] => 437
                            [1] => 7777
                        )

                    [1] => Array
                        (
                            [0] => 437
                            [1] => 7777
                        )
                )
            [6000] => Array
                (
                    [0] => Array
                        (
                            [0] => 437
                            [1] => 6000
                        )

                    [1] => Array
                        (
                            [0] => 437
                            [1] => 6000
                        )
                )
            [others] => Array
                (
                    [0] => Array
                        (
                            [0] => 437
                            [1] => 1000
                        )

                    [1] => Array
                        (
                            [0] => 437
                            [1] => 4000
                        )

                    [2] => Array
                        (
                            [0] => 437
                            [1] => 4000
                        )

                    [3] => Array
                        (
                            [0] => 437
                            [1] => 5000
                        )
                )

        )

)

Solution

  • Try this :

    // Create a new array
    $result = array();
    
    // Loop through your array
    foreach ($array as $value) {
        // Create a key that start at 0
        $i = 0;
        // Test if $result[0] exist : if yes, you have data, else you have nothing
        if (isset($result[$i])) {
            do {
                // Check if the 'name' is new : if yes, $i++ to check next name
                if ($result[$i]['name'] !== $value['name']) $i++;
                // If you find similar name, stop here
                else break;
            } while (isset($result[$i]));
        // Just add $result[0] with name and age value
        } else {
            $result[$i] = array (
                'name' => $value['name'],
                'age'  => $value['age']
            );
        }
        // Now you know the index of result you need to work with
        // Just add a new code / group array to your code index
        $result[$i][$value['group']][] = array($value['code'], $value['group']);
    }
    

    If you do var_dump($result); the output is :

    array (size=1)
    0 => 
      array (size=7)
        'name' => string 'John Doe' (length=8)
        'age' => string '36' (length=2)
        1000 => 
          array (size=1)
            0 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '1000' (length=4)
        7777 => 
          array (size=2)
            0 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '7777' (length=4)
            1 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '7777' (length=4)
        4000 => 
          array (size=2)
            0 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '4000' (length=4)
            1 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '4000' (length=4)
        5000 => 
          array (size=1)
            0 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '5000' (length=4)
        6000 => 
          array (size=2)
            0 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '6000' (length=4)
            1 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '6000' (length=4)
    

    EDIT :

    To get only group value equal to 7777 and 6000 replace

    $result[$i][$value['group']][] = array($value['code'], $value['group']);
    

    by

    $group_value = $value['group'] == "7777" || $value['group'] == "6000" ? $value['group'] : "Others";
    $result[$i][$group_value][] = array($value['code'], $value['group']);
    

    Now the output of var_dump($result); is :

    array (size=1)
      0 => 
      array (size=5)
        'name' => string 'John Doe' (length=8)
        'age' => string '36' (length=2)
        'Others' => 
          array (size=4)
            0 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '1000' (length=4)
            1 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '4000' (length=4)
            2 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '4000' (length=4)
            3 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '5000' (length=4)
        7777 => 
          array (size=2)
            0 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '7777' (length=4)
            1 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '7777' (length=4)
        6000 => 
          array (size=2)
            0 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '6000' (length=4)
            1 => 
              array (size=2)
                0 => string '437' (length=3)
                1 => string '6000' (length=4)
    

    Is it what you want?