2

situation

I have an array result returned from an Database call. In the example below, it fetches many Genres which can have many books. Using a join, the query pulls the books from each genre at the same time. Here is a hypothetical result set:

array(
    [0] => array (
        'id' => 1,
        'title' => 'ficton'
        'modules' => array(
            [0] => array(
                'other_id' => 1
                'other_title' => 'James Clavell'
            ),
            [1] => array(
                'other_id' => 2
                'other_title' => 'Terry Pratchett'
            ),
            [2] => array(
                'other_id' => 3
                'other_title' => 'Robert Ludlum'
            ),
        ),
    [1] => array (
        'id' => 2,
        'title' => 'non-ficton'
        'modules' => array(
            [1] => array(
                'other_id' => 5
                'other_title' => 'An excessive book of excessively interesting things'
            ),
            [2] => array(
                'other_id' => 6
                'other_title' => 'It\'s late, I can\'t think of what to put here'
            ),
        )
    )
)

Situation

What I would like to end up with is an array which contains only the modules as shown below:

array(
    [0] => array(
        'other_id' => 1
        'other_title' => 'James Clavell'
    ),
    [1] => array(
        'other_id' => 2
        'other_title' => 'Terry Pratchett'
    ),
    [2] => array(
        'other_id' => 3
        'other_title' => 'Robert Ludlum'
    ),
    [3] => array(
        'other_id' => 5
        'other_title' => 'An excessive book of excessively interesting things'
    ),
    [4] => array(
        'other_id' => 6
        'other_title' => 'It\'s late, I can\'t think of what to put here'
    )
)

Problem

Now, I have no problem achieving this through iteration but, feel there is a much better (undiscovered) means to achieving this.

Question

Is a shortcut to creating the desired result. The code I have so far is listed below and it's not a difficult situation to solve. I'm more just curious as to whether there is a much BETTER version of doing the following.

Ugly code that works

Here is a version of the code that 100% works but, features more iteration than I could care for.

$aryTemp = array();
foreach($aryGenres as $intKey => $aryGenre) {
    foreach($aryGenre['modules'] as $aryModule) {
        $aryTemp[] = $aryModule
    }
}

Attempt using array map

An attempt using array map and failing horribly

$aryTemp = array();
foreach($aryGenres as $intKey => $aryGenre) {
    $aryTemp[] = array_map(
        function($aryRun) { return $aryRun;
    },$aryGenre['modules']

}

I would love to be able to cut out the foreach loop as shown above.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Simon
  • 816
  • 2
  • 7
  • 16
  • Wouldn't it be easier to modify your query to return what you want? – vascowhite Aug 07 '13 at 09:37
  • @vascowhite I could make the DB call prick out the data I want but then, I wouldn't get the genre record in its' fullest in the first returned result set. The end goal is to have shorter and "simpler" more efficient runtime code. – Simon Aug 07 '13 at 09:49
  • This page/task is the child of two parent pages/tasks on Stack Overflow: [Is there a function to extract a 'column' from an array in PHP?](https://stackoverflow.com/q/1494953/2943403) and [How to Flatten a Multidimensional Array?](https://stackoverflow.com/q/1319903/2943403) – mickmackusa Sep 04 '22 at 04:03

1 Answers1

3

PHP 5.6+:

$modules = array_merge(...array_column($arr, 'modules'));

# Allowing empty array
$modules = array_merge([], ...array_column($arr, 'modules'));

PHP 5.5:

$modules = call_user_func_array('array_merge', array_column($arr, 'modules'));

PHP ~5.4:

$modules = call_user_func_array(
    'array_merge',
    array_map(
        function ($i) {
            return $i['modules'];
        },
        $arr
    )
);
mpyw
  • 5,526
  • 4
  • 30
  • 36