29

I have an array of arrays, with the following structure :

array(array('page' => 'page1', 'name' => 'pagename1')
      array('page' => 'page2', 'name' => 'pagename2')
      array('page' => 'page3', 'name' => 'pagename3'))

Is there a built-in function that will return a new array with just the values of the 'name' keys? so I'd get:

array('pagename1', 'pagename2', 'pagename3')
0

14 Answers 14

83

As of PHP 5.5 you can use array_column():

<?php
$samples=array(
            array('page' => 'page1', 'name' => 'pagename1'),
            array('page' => 'page2', 'name' => 'pagename2'),
            array('page' => 'page3', 'name' => 'pagename3')
            );
$names = array_column($samples, 'name');
print_r($names);

See it in action

Sign up to request clarification or add additional context in comments.

5 Comments

Nice, thanks John. I have been researching into PHP 5.5, but I hadn't seen this
This should be the correct answer by now since php has added the built in function which exactly what the OP is asking.
@John Conde, someone must have it in for you today as a lot of your posts are being flagged as low quality...
@Option Thanks for the heads up. If they're flagging stuff like this I don't think anything is going to come of it. But they are wasting people's time which is a shame.
@John, no problem whatsoever Im unsure if you can flag this to staff to place a prevention on it or not.. Nevertheless, I have marked all as fine as I'm sure others will too :)
19

Why does it have to be a built in function? No, there is none, write your own.

Here is a nice and easy one, as opposed to others in this thread.

$namearray = array();

foreach ($array as $item) {
    $namearray[] = $item['name'];
}

In some cases where the keys aren't named you could instead do something like this

$namearray = array();

foreach ($array as $key => $value) {
    $namearray [] = $value;
}

6 Comments

Okay, given your recent edit ('easy one, as opposed to others') I'll bite ;) If you turn your code into a real function as per the original request, it will be about as 'complex' as the the array_map() or array_walk() examples below, especially if you'd care to add an execution example.
Yeah I think mine is the most elegant given PHP's features and the first complete example. :)
Hi, thanks. All I actually asked in my question was if there is a built-in function - I don't like to reinvent the wheel. You gave me an answer to that, and your solution is basically what I would have written.
Will issue a notice or warning, if one of the arrays doesn't have a name entry. Just sayin'
The correct answer to "Is there a built-in function?" is the answer of John Conde below.
|
14

Here's a functional way of doing it:

$data = array(
            array('page' => 'page1', 'name' => 'pagename1'),
            array('page' => 'page2', 'name' => 'pagename2'),
            array('page' => 'page3', 'name' => 'pagename3'));

$result = array_map(create_function('$arr', 'return $arr["name"];'), $data);
print_r($result);

1 Comment

I like this, and the lambda in it fits nicely with my brain at the moment, as I've been learning Scheme. +1
6

Well there is. At least for PHP > 5.5.0 and it is called array_column

The PHP function takes an optional $index_keyparameter that - as per the PHP website - states:

$index_key

The column to use as the index/keys for the returned array. This value may be the integer key of the column, or it may be the string key name

In the answers here, i see a stripped version without the optional parameter. I needed it, so, here is the complete function:

if (!function_exists('array_column')) {
    function array_column($array, $column, $index_key = null) {
        $toret = array();
        foreach ($array as $key => $value) {
            if ($index_key === null){
                $toret[] = $value[$column];
            }else{
                $toret[$value[$index_key]] = $value[$column];
            }
        }
        return $toret;
    }
}

Comments

1

Similar to fuentesjrs solution, but a bit more generic using array_walk() with a custom callback:

// Define the callback
function extract_named_sub_elements(&$item, $key, $name) {
  $item = $item[$name];
}

// Test data
$original = array(
  array('page' => 'page1', 'name' => 'pagename1'),
  array('page' => 'page2', 'name' => 'pagename2'),
  array('page' => 'page3', 'name' => 'pagename3'),
);

// Use a copy, as array_walk() operates directly on the passed in array
$copy = $original;

// Substitute 'name' with whatever element you want to extract, e.g. 'page'
array_walk($copy, 'extract_named_sub_elements', 'name');

print_r($copy);

Comments

1
if (!function_exists('array_column')) {
    function array_column($array,$column) {
    $col = array();
    foreach ($array as $k => $v) {
        $col[]=$v[$column];
    }
    return $col;
    }
}

This should work for php versions < 5.5 and degrade in case the function exist

Comments

1

Yes, there is a php built-in function called array_column which does what you are looking for.

You would call it something like $name_keys = array_column($array, 'name'); to get the result that you are looking for.

Please refer to the following entry in the PHP manual for more details:

http://php.net/manual/en/function.array-column.php

2 Comments

This answer is only valid if the PHP version is greater than 5.
Greater than 5.5, to be exact.
1

Consider this sample input array to expose nuanced differences in script behaviors:

$array = [
    'a' => ['page' => 'page1', 'name' => 'pagename1'],
    'b' => ['page' => 'page2', 'name' => 'pagename2'],
    'c' => ['page' => 'page3', 'name' => 'pagename3'],
    'd' => ['page' => 'page4',],
];
  • Populate a new indexed array from column values with array_column(): (Demo)

    var_export(array_column($array, 'name'));
    # array (
    #   0 => 'pagename1',
    #   1 => 'pagename2',
    #   2 => 'pagename3',
    # )
    

    Missing column values are no problem.

  • Populate a new array preserving first level keys with array_map(): (Demo)

    var_export(array_map(fn($row) => $row['name'] ?? 'missing', $array));
    # array (
    #   'a' => 'pagename1',
    #   'b' => 'pagename2',
    #   'c' => 'pagename3',
    #   'd' => 'missing',
    # )
    

    Missing column values must be explicitly handled to avoid an error.

  • Populate a new indexed array from column values with array_reduce(): (Demo)

    var_export(array_reduce($array, fn($result, $row) => array_merge($result, [$row['name'] ?? 'missing']), []));
    # array (
    #   0 => 'pagename1',
    #   1 => 'pagename2',
    #   2 => 'pagename3',
    #   3 => 'missing',
    # )
    

    Missing column values must be explicitly handled to avoid an error.

  • Overwrite the rows of the original array with the column values with array_walk(): (Demo)

    array_walk($array, fn(&$row) => $row = $row['name'] ?? 'missing');
    var_export($array);
    # array (
    #   'a' => 'pagename1',
    #   'b' => 'pagename2',
    #   'c' => 'pagename3',
    #   'd' => 'missing',
    # )
    

    Missing column values must be explicitly handled to avoid an error.

  • If all rows contain the sought column value, then a body-less loop can be used with array destructuring to avoid declaring a temporary variable: (Demo)

    $result = [];
    foreach ($array as ['name' => $result[]]);
    var_export($result);
    

    Note that you cannot declare the first level key as a variable and use it as the key in the result array with this approach because values are assigned BEFORE keys are assigned.

    If you need to handle potentially missing columns, then a classic loop with a null coalesced default value is suitable. (Demo)

    $result = [];
    foreach ($array as $row) {
        $result[] = $row['name'] ?? 'missing';
    }
    var_export($result);
    

    If you want to merely mutate the original input array instead of generating a new array, then use a foreach loop and modify the rows by reference. (Demo)

    foreach ($array as &$row) {
        $row = $row['name'] ?? 'missing';
    }
    var_export($array);
    
  • Certainly recursion is overkill for this simple task, but for completeness, array_walk_recursive() can be used to access "leaf nodes" in the structure and collect qualifying values in the $result array by reference. (Demo)

    $colName = 'name';
    
    $result = [];
    array_walk_recursive(
        $array,
        function ($v, $k) use ($colName, &$result) {
            if ($k === $colName) {
                $result[] = $v;
            }
        }
    );
    var_export($result);
    

1 Comment

@rosh that is an antipattern that no one should ever use. Required reading: Generate an associative array from an array of rows using one column as keys and another column as values
0

You can extend the ArrayIterator class and override the method mixed current(void).

class Foo extends ArrayIterator {
  protected $index;
  public function __construct($array, $index) {
    parent::__construct($array);
    $this->index = $index;
  }

  public function current() {
    $c = parent::current();
    return isset($c[$this->index]) ? $c[$this->index] : null;
  }
}

$a = array(
  array('page' => 'page1', 'name' => 'pagename1'),
  array('name' => '---'),
  array('page' => 'page2', 'name' => 'pagename2'),
  array('page' => 'page3', 'name' => 'pagename3')
);

$f = new Foo($a, 'page');
foreach($f as $e) {
  echo $e, "\n";
}

prints

page1

page2
page3

Comments

0

I don't think there is any need to have a built in function for this. There may be an array in your those array.

$samples=array(
            array('page' => 'page1', 'name' => 'pagename1'),
            array('page' => 'page2', 'name' => 'pagename2'),
            array('page' => 'page3', 'name' => 'pagename3')
            );

$output1=array();
$output2=array();
foreach($samples as $sample){
    array_push($output1,$sample['name']);
    $output2[]=array_splice($sample,1);

}

print_r($output1);
print_r($output2);

in $output1 is the output what you want if you want only to remove the 'page' indexing' part then $output2.

if you need all the values from the that array and indexes numerically the array then you can use

$array_1=array_values($samples); 

but what i understand, you didn't want this.

Comments

0

Not a 'built-in', but short arrow functions make for abrreviated explicit coding (introduced in Php v7.4.) and can be used with array_map for array transformations.

Here applying a callback to each member of the array that returns the desired attribute from each subarray:

<?php
$data =
[
    ['page' => 'page1', 'name' => 'pagename1'],
    ['page' => 'page2', 'name' => 'pagename2'],
    ['page' => 'page3', 'name' => 'pagename3']
];

$names = array_map(fn($v) => $v['name'], $data);
var_export($names);

Output:

array (
    0 => 'pagename1',
    1 => 'pagename2',
    2 => 'pagename3',
  )

The OP posted this question before array_column exisited (from Php 5.5.0). This answers the original question with a short solution:

$names = array_column($data, 'name');

But a simple loop is also trite:

foreach($data as $item) $names[] = $item['name'];

1 Comment

This is a newer equivalent of this: stackoverflow.com/a/1495005/3392762
0

With array_reduce:

$names = array_reduce($array, function ($carry, $item) {
    return array_merge($carry, [$item['name']]);
}, []);

4 Comments

what does array_reduce do? Please explain it rather than just paste some code without explanation. Cheers
@Martin agree it could do with some edit, but as Tony hasn't been seen since 2016 the onus falls on someone else. Most of the submissions could be improved. Especially as other questons redirect here.
Intution here is that pushing/appending to the carry and then returning the carry would be more performant than many merges.
@Progrock I saw this post was on the front page, so looked at what was "active today" and this answer was highlighted. I had overlooked the date of the answer and has assumed it was a new answer from a user.
0

You can get column, bind key value as well:

$a = array(
          array(
            'id' => 5698,
            'first_name' => 'Peter',
            'last_name' => 'Griffin',
          ),
          array(
            'id' => 4767,
            'first_name' => 'Ben',
            'last_name' => 'Smith',
          ),
          array(
            'id' => 3809,
            'first_name' => 'Joe',
            'last_name' => 'Doe',
          )
        );

if you want only column then use:

$last_names = array_column($a, 'last_name');
print_r($last_names);
        

if you want to bind key and values then use:

$last_names = array_column($a, 'last_name', 'id');
print_r($last_names);
    

Comments

-1

Just to extend on some of the answers here, as of PHP 5.5, array_column is what you want.

It actually has a few possible uses.

Using the sample array below, here are the different ways to use array_column.

$a = array(
    array('id' => '1', 'name' => 'Joe'),
    array('id' => '2', 'name' => 'Jane')
);

Retrieving a single column as the array

$b = array_column($a, 'name');

Would give you. Notice the auto keys starting from 0, as per a normal array.

$b[0] = 'Joe';
$b[1] = 'Jane';

Retrieving the full array with a column as the index.

$c = array_column($a, NULL, 'id');

Would result in the following.

$c[1] = array('id' => '1', 'name' => 'Joe');
$c[2] = array('id' => '2', 'name' => 'Jane');

Notice how the column I selected as the third parameter becomes the key for each item and I get the full array by setting the second parameter to null.

Of course, the final usage is to set both the 2nd and 3rd params.

$d = array_column($a, 'name', 'id');

Would give you the following.

$d[1] = 'Joe';
$d[2] = 'Jane';

I personally use the full 3 params for creating select option lists. If I have a table with my options, I query the table and get the result and pass it into this to get a list with the key as the value and the label. This is a brilliant way for building info sets that need to intersect by the index as well.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.