Isolate a single column in a multi-dimensional array - php

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;

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.

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;
}

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.

Simply put, no.
You will need to use a loop or a callback function like array_walk.

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.

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;
}

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

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.

You could do:
$tmp = array_flip($names);
$names = array_keys($tmp);

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;
}
}

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'));

Related

Rearrange array to code optimization [duplicate]

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')
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
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;
}
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);
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;
}
}
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);
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
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
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
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.
There is a built-in function actually, it's called array_column(...).
Here is all you need to know about it : https://www.php.net/manual/fr/function.array-column.php
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'];
With array_reduce:
$names = array_reduce($array, function ($carry, $item) {
return array_merge($carry, [$item['name']]);
}, []);
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);
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.
I wanted to post here, even if this is an old question, because it is still very relevant and many developers do not use PHP >= 5.5
Let's say you have an array like this:
Array
(
[files] => Array
(
[name] => Array
(
[0] => file 1
[1] => file 2
[2] => file 3
)
[size] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[error] => Array
(
[0] => abc
[1] => def
[2] => ghi
)
)
)
and the output you want is something like this:
Array
(
[0] => Array
(
[0] => file 1
[1] => 1
[2] => abc
)
[1] => Array
(
[0] => file 2
[1] => 2
[2] => def
)
[2] => Array
(
[0] => file 3
[1] => 3
[2] => ghi
)
)
You can simply use the array_map() method without a function name passed as the first parameter, like so:
array_map(null, $a['files']['name'], $a['files']['size'], $a['files']['error']);
Unfortunately you cannot map the keys if passing more than one array.

Array list for all id [duplicate]

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')
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
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;
}
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);
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;
}
}
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);
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
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
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
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.
There is a built-in function actually, it's called array_column(...).
Here is all you need to know about it : https://www.php.net/manual/fr/function.array-column.php
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'];
With array_reduce:
$names = array_reduce($array, function ($carry, $item) {
return array_merge($carry, [$item['name']]);
}, []);
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);
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.
I wanted to post here, even if this is an old question, because it is still very relevant and many developers do not use PHP >= 5.5
Let's say you have an array like this:
Array
(
[files] => Array
(
[name] => Array
(
[0] => file 1
[1] => file 2
[2] => file 3
)
[size] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[error] => Array
(
[0] => abc
[1] => def
[2] => ghi
)
)
)
and the output you want is something like this:
Array
(
[0] => Array
(
[0] => file 1
[1] => 1
[2] => abc
)
[1] => Array
(
[0] => file 2
[1] => 2
[2] => def
)
[2] => Array
(
[0] => file 3
[1] => 3
[2] => ghi
)
)
You can simply use the array_map() method without a function name passed as the first parameter, like so:
array_map(null, $a['files']['name'], $a['files']['size'], $a['files']['error']);
Unfortunately you cannot map the keys if passing more than one array.

What PHP Array Function do I use to convert a multidimensional associative array

I want to convert this.
$data1 = array(
array('value' => '100.00', 'total' => '32'),
array('value' => '10.00', 'total' => '13'),
array('value' => '200.00', 'total' => '39'),
array('value' => '190.00', 'total' => '11'),
);
into this
$data2 = array(
'value' => array(0 => '100.00', 1 => '10.00', 2 => '200.00', 3 => '190.00'),
'total' => array(0 => '32', 1 => '13', 2 => '39', 3 => '11')
);
I can obviously do this in a roundabout way by iterating over the top array, while appending to a series of arrays, but I figured that there must be a php array function that I don't know about that can do this more concisely.
http://www.php.net/manual/en/ref.array.php
Values are floats and integers (if it makes any difference), I've just added them as strings in the example code because it's easier to read IMO. Final array order should match the initial order. I'll award the correct answer to the least LOC providing performance isn't significantly worse that the 'long' version. PHP 5.4.
If PHP had an array_pluck function, it would be simple.
function array_pluck(array $array, $field)
{
return array_map(function($row) use ($field) { return $row[$field]; }, $array);
}
$data2 = array(
'value' => array_pluck($data1, 'value'),
'total' => array_pluck($data1, 'total')
);
I think that's about as easy as it is to read, but you'll be looping over the entire array once per field, so it's hardly the optimal solution.
Personally, this is a situation where I'd probably stick with the foreach solution but try to wrap it inside some reusable function.
<?php // php 5.4 array syntax
$new = array_reduce($data1, function (&$result, $item)
{
$result['value'][] = $item['value'];
$result['total'][] = $item['total'];
return $result;
},
['value' => [], 'total' => []]);
'value' and 'total' are arbitrary names, so you're not going to get a one-liner php library function to do this.
You can refactor this code into a function if you want to...
function array_rotate($data) {
$k = array_keys($data[0]);
return array_reduce($data, function (&$r, $i) use ($k) {
$r[$k[0]][] = $i[$k[0]];
$r[$k[1]][] = $i[$k[1]];
return $r;
}, [$k[0] => [], $k[1] => []]);
}
I generalised #matthew's code, this allows an arbitrary number of keys (instead of 2):
function array_rotate2($data) {
return array_combine(array_keys($data[0]),
array_map(function ($field) use ($data) {
return array_map(function($row) use ($field) { return $row[$field]; }, $data);
}, array_keys($data[0])));
}
You can do it without a function using a simple foreach():
<?php
$data = array(
array('value' => '100.00', 'total' => '32'),
array('value' => '10.00', 'total' => '13'),
array('value' => '200.00', 'total' => '39'),
array('value' => '190.00', 'total' => '11'),
);
$newArray = array();
$i=0;
foreach($data as $value){
$newArray["value"][] = $data[$i]["value"];
$newArray["total"][] = $data[$i]["total"];
$i++;
}
echo "<pre>";
print_r($newArray);
echo "</pre>";
?>
Prints this:
Array
(
[value] => Array
(
[0] => 100.00
[1] => 10.00
[2] => 200.00
[3] => 190.00
)
[total] => Array
(
[0] => 32
[1] => 13
[2] => 39
[3] => 11
)
)
$final = array();
foreach($data1 as $array) {
foreach($array as $key => $value) {
$final[$key] = isset($final[$key]) ? $final : array();
$final[$key][] = $value;
}
}
Like others are saying I don't think there is a one-liner. Here is a reusable foreach function that should work
function array_multi_key_combine($a, $keys = array()) {
$b = array();
foreach($a as $v) {
foreach($keys as $k) {
if(isset($v[$k])) $b[$k][] = $v[$k];
}
}
return $b;
}
$data2 = array_multi_key_combine($data1, array('value', 'total'));

PHP multidimensional array conversion using array_map/array_walk functions

I have the following multidimensional array:
$userList = array(
0 => array('id' => 1000, 'first_name' => 'John', 'last_name' => 'Smith'),
1 => array('id' => 1001, 'first_name' => 'Sam', 'last_name' => 'Johnson'),
);
I want to convert it to the array like:
$userData = array(
1000 => 'John Smith',
1001 => 'Sam Johnson',
);
It's quite obvious for me how to implement this using foreach loop, but I wonder if it's possible to do this with PHP array functions like array_map or array_walk. Please use PHP 5.3 for the callback function. Thank you!
Since those functions only work on the array values, getting them to set the key in the new array is somewhat awkward. One way to do it is:
$arr = array_combine(
array_map(function ($i) { return $i['id']; }, $arr),
array_map(function ($i) { return "$i[first_name] $i[last_name]"; }, $arr)
);
This is a case where a foreach is much more appropriate.
A minor trick from the functional programming.
$arr = array_reduce(
$arr,
function ($result, $item) {
$result[$item['id']] = $item['first_name'] . ' ' . $item['last_name'];
return $result;
},
array()
);
See array_reduce().
Code:
<?php
function convertArray ( $array ) {
$newUserList = array();
foreach ( $array as $value ) {
$newUserList[ $value[ 'id' ] ] = $value[ 'first_name' ] . ' ' . $value[ 'last_name' ];
}
return $newUserList;
}
$userList = array(
0 => array( 'id' => 1000, 'first_name' => 'John', 'last_name' => 'Smith' ),
1 => array( 'id' => 1001, 'first_name' => 'Sam', 'last_name' => 'Johnson' )
);
$newUserList = convertArray( $userList );
?>
Output:
Array
(
[1000] => John Smith
[1001] => Sam Johnson
)

Is there a function to extract a 'column' from an array in PHP?

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')
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
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;
}
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);
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;
}
}
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);
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
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
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
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.
There is a built-in function actually, it's called array_column(...).
Here is all you need to know about it : https://www.php.net/manual/fr/function.array-column.php
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'];
With array_reduce:
$names = array_reduce($array, function ($carry, $item) {
return array_merge($carry, [$item['name']]);
}, []);
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);
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.
I wanted to post here, even if this is an old question, because it is still very relevant and many developers do not use PHP >= 5.5
Let's say you have an array like this:
Array
(
[files] => Array
(
[name] => Array
(
[0] => file 1
[1] => file 2
[2] => file 3
)
[size] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[error] => Array
(
[0] => abc
[1] => def
[2] => ghi
)
)
)
and the output you want is something like this:
Array
(
[0] => Array
(
[0] => file 1
[1] => 1
[2] => abc
)
[1] => Array
(
[0] => file 2
[1] => 2
[2] => def
)
[2] => Array
(
[0] => file 3
[1] => 3
[2] => ghi
)
)
You can simply use the array_map() method without a function name passed as the first parameter, like so:
array_map(null, $a['files']['name'], $a['files']['size'], $a['files']['error']);
Unfortunately you cannot map the keys if passing more than one array.

Categories