سؤال

How can I split a single array into it's sub-keys?

$arr = array(
             0 => array(
                        'foo' => '1',
                        'bar' => 'A'
                       ),
             1 => array(
                        'foo' => '2',
                        'bar' => 'B'
                       ),
             2 => array(
                        'foo' => '3',
                        'bar' => 'C'
                       )
            );

What is the most efficient way to return an array of foo and bar separately?

I need to get here:

$foo = array('1','2','3');
$bar = array('A','B','C');

I'm hoping there's a clever way to do this using array_map or something similar. Any ideas?

Or do I have to loop through and build each array that way? Something like:

foreach ($arr as $v) {
    $foo[] = $v['foo'];
    $bar[] = $v['bar'];
}
هل كانت مفيدة؟

المحلول

In a lucky coincidence, I needed to do almost the exact same thing earlier today. You can use array_map() in combination with array_shift():

$foo = array_map('array_shift', &$arr);
$bar = array_map('array_shift', &$arr);

Note that $arr is passed by reference! If you don't do that, then each time it would return the contents of $arr[<index>]['foo']. However, again because of the reference - you won't be able to reuse $arr, so if you need to do that - copy it first.

The downside is that your array keys need to be ordered in the same way as in your example, because array_shift() doesn't actually know what the key is. It will NOT work on the following array:

$arr = array(
    0 => array(
        'foo' => '1',
        'bar' => 'A'
    ),
    1 => array(
        'bar' => 'B',
        'foo' => '2'
    ),
    2 => array(
        'foo' => '3',
        'bar' => 'C'
    )
);

Update:

After reading the comments, it became evident that my solution triggers E_DEPRECATED warnings for call-time-pass-by-reference. Here's the suggested (and accepted as an answer) alternative by @Baba, which takes advantage of the two needed keys being the first and last elements of the second-dimension arrays:

$foo = array_map('array_shift', $arr);
$bar = array_map('array_pop', $arr);

نصائح أخرى

$n = array();

foreach($arr as $key=>$val) {
    foreach($val as $k=>$v) {
        $n[$k][] = $v;
    }
}

array_merge_recursive will combine scalar values with the same key into an array. e.g.:

array_merge_recursive(array('a',1), array('b',2)) === array(array('a','b'),array(1,2));

You can use this property to simply apply array_merge_recursive over each array in your array as a separate argument:

call_user_func_array('array_merge_recursive', $arr);

You will get this result:

array (
  'foo' => 
  array (
    0 => '1',
    1 => '2',
    2 => '3',
  ),
  'bar' => 
  array (
    0 => 'A',
    1 => 'B',
    2 => 'C',
  ),
)

It won't even be confused by keys in different order.

However, every merged value must be scalar! Arrays will be merged instead of added as a sub-array:

array_merge_recursive(array(1), array(array(2)) === array(array(1,2))

It does not produce array(array(1, array(2)))!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top