21

Say for example you just queried a database and you recieved this 2D array.

$results = array(
    array('id' => 1, 'name' => 'red'  , 'spin' =>  1),
    array('id' => 2, 'name' => 'green', 'spin' => -1),
    array('id' => 3, 'name' => 'blue' , 'spin' => .5)
);

I often find myself writing loops like this.

foreach($results as $result)
    $names[] = $result['name'];

My questions is does there exist a way to get this array $names without using a loop? Using callback functions count as using a loop.

Here is a more generic example of getting every field.

foreach($results as $result)
    foreach($result as $key => $value)
        $fields[$key][] = $value;
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
gradbot
  • 13,732
  • 5
  • 36
  • 69

11 Answers11

23

As of June 20th in PHP-5.5 there is a new function array_column

For example:

$records = array(
    array(
        'id' => 2135,
        'first_name' => 'John',
        'last_name' => 'Doe'
    ),
    array(
        'id' => 3245,
        'first_name' => 'Sally',
        'last_name' => 'Smith'
    ),
    array(
        'id' => 5342,
        'first_name' => 'Jane',
        'last_name' => 'Jones'
    ),
    array(
        'id' => 5623,
        'first_name' => 'Peter',
        'last_name' => 'Doe'
    )
);


$firstNames = array_column($records, 'first_name');
print_r($firstNames);

Will return

Array
(
    [0] => John
    [1] => Sally
    [2] => Jane
    [3] => Peter
)

There are even more examples in the above mentioned link.

Lorenz Meyer
  • 19,166
  • 22
  • 75
  • 121
Salvador Dali
  • 214,103
  • 147
  • 703
  • 753
14

I voted @Devon's response up because there really isn't a way to do what you're asking with a built-in function. The best you can do is write your own:

function array_column($array, $column)
{
    $ret = array();
    foreach ($array as $row) $ret[] = $row[$column];
    return $ret;
}
Philipp Kyeck
  • 18,402
  • 15
  • 86
  • 123
inxilpro
  • 20,094
  • 2
  • 24
  • 28
  • 4
    Bugs my that you haven't declared `ret`, even if you don't technically need to in PHP. (`$ret = array();`) – mpen Oct 04 '11 at 20:45
  • @Quentin please inform the answering user of anything you think is wrong about the answer rather than quietly correcting it. – Timothy Groote Jun 18 '13 at 11:48
  • 1
    That was Mark's comment about initializing `$ret`. I upvoted Mark's comment, offered a change in the answer with an explanation attached. I should have added a comment here as well? – Quentin Jun 20 '13 at 08:18
  • Ironic that PHP had included a core function with exact same label `array_column()`..!! Were you involved? – Fr0zenFyr May 10 '15 at 22:52
  • 1
    @Fr0zenFyr haha, nope. Just a coincidence :) – inxilpro May 11 '15 at 14:13
7

Starting PHP 5.3, you can use this pretty call with lambda function:

$names = array_map(function ($v){ return $v['name']; }, $results);

This will return array sliced by 'name' dimension.

Alexey Petushkov
  • 2,010
  • 19
  • 19
5

Simply put, no.

You will need to use a loop or a callback function like array_walk.

Devon
  • 5,786
  • 5
  • 38
  • 46
2

I did more research on this and found that ruby and prototype both have a function that does this called array_pluck,2. It's interesting that array_map has a second use that allows you to do the inverse of what i want to do here. I also found a PHP class someone is writing to emulate prototypes manipulation of arrays.

I'm going to do some more digging around and if I don't find anything else I'll work on a patch to submit to the internals@lists.php.net mailing list and see if they will add array_pluck.

gradbot
  • 13,732
  • 5
  • 36
  • 69
2

For those of you that cannot upgrade to PHP5.5 right now and need this function, here is an implementation of array_column.

function array_column($array, $column){
    $a2 = array();
    array_map(function ($a1) use ($column, &$a2){
        array_push($a2, $a1[$column]);
    }, $array);
    return $a2;
}
MirroredFate
  • 12,396
  • 14
  • 68
  • 100
1

If you are running a version of PHP before 5.5 and array_column(), you can use the official replacement in plain PHP:

https://github.com/ramsey/array_column

JohnK
  • 6,865
  • 8
  • 49
  • 75
0

You could do:

$tmp = array_flip($names);
$names = array_keys($tmp);
cheesemacfly
  • 11,622
  • 11
  • 53
  • 72
0

I think this will do what you want

array_uintersect_uassoc

You would have to do something like this

$results = array(
    array('id' => 1, 'name' => 'red'  , 'spin' =>  1),
    array('id' => 2, 'name' => 'green', 'spin' => -1),
    array('id' => 3, 'name' => 'blue' , 'spin' => .5)
);
$name = array_uintersect_uassoc( $results, array('name' => 'value')  , 0, "cmpKey");
print_r($name);

//////////////////////////////////////////////////
// FUNCTIONS
//////////////////////////////////////////////////
function cmpKey($key1, $key2) {
  if ($key1 == $key2) {
    return 0;
  } else {
    return -1;
  }
}

However, I don't have access to PHP5 so I haven't tested this.

Bill
  • 4,323
  • 8
  • 28
  • 32
  • This did not work for me in PHP5. I got a Not a valid callback warning and an empty array. – Devon Oct 02 '08 at 20:29
  • It's failing because you have to pass a function not 0. Even if i pass a function that always returns true or false to this i still don't get a valid answer. You can't use array intersect because it's an array inside of an array. You can use array_walk or array_map depending on return type. – gradbot Oct 06 '08 at 19:57
0

This is fast function alternative of array_column()

if(!function_exists('array_column')) {
    function array_column($element_name) {
        $ele =   array_map(function($element) {
            return $element[$element_name];
        }, $a);
        return  $ele;
    }
}
Manoj Sharma
  • 1,467
  • 2
  • 13
  • 20
Keshav Kalra
  • 305
  • 5
  • 8
0

other alternative

 function transpose(array $array): array
 {
     $out = array();
     foreach ($array as $rowkey => $row) {
        foreach ($row as $colkey => $col) {
                $out[$colkey][$rowkey] = $col;
         }
     }
        return $out;
 }

 function filter_columns(array $arr, string ...$columns): array
 {
     return array_intersect_key($arr, array_flip($columns));
 }

test

$results = array(
    array('id' => 1, 'name' => 'red'  , 'spin' =>  1),
    array('id' => 2, 'name' => 'green', 'spin' => -1),
    array('id' => 3, 'name' => 'blue' , 'spin' => .5)
);

 var_dump(filter_columns(transpose($results),'name'));
 var_dump(filter_columns(transpose($results),'id','name'));
 var_dump(filter_columns(transpose($results),'id','spin'));