如果不存在 array_column,以下解决方案将起作用。
if(!function_exists("array_column"))
{
function array_column($array,$column_name)
{
return array_map(function($element) use($column_name){return $element[$column_name];}, $array);
}
}
(PHP 5 >= 5.5.0, PHP 7, PHP 8)
array_column — 返回输入数组中单个列的值
array_column() 返回 array
中单个列的值,该列由 column_key
标识。可选地,可以提供 index_key
,以根据输入数组的 index_key
列中的值对返回数组中的值进行索引。
array
一个多维数组或一个对象数组,从中提取一列值。如果提供了对象数组,则可以直接提取公共属性。为了提取受保护或私有属性,该类必须同时实现 __get() 和 __isset() 魔术方法。
column_key
要返回的值的列。此值可以是您希望检索的列的整数键,也可以是关联数组或属性名称的字符串键名。它也可以是 空
以返回完整的数组或对象(这与 index_key
一起使用以重新索引数组非常有用)。
index_key
用作返回数组的索引/键的列。此值可以是列的整数键,也可以是字符串键名。该值像往常一样被 强制转换 为数组键(但是,在 PHP 8.0.0 之前,也允许支持转换为字符串的对象)。
返回一个值数组,表示输入数组中的一列。
示例 #1 从记录集中获取姓名的列
<?php
// 表示数据库返回的可能记录集的数组
$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',
)
);
$first_names = array_column($records, 'first_name');
print_r($first_names);
?>
以上示例将输出
Array ( [0] => John [1] => Sally [2] => Jane [3] => Peter )
示例 #2 获取记录集中姓氏的列,并以“id”列作为索引
<?php
// 使用示例 #1 中的 $records 数组
$last_names = array_column($records, 'last_name', 'id');
print_r($last_names);
?>
以上示例将输出
Array ( [2135] => Doe [3245] => Smith [5342] => Jones [5623] => Doe )
示例 #3 从对象的公共“username”属性获取用户名列
<?php
class User
{
public $username;
public function __construct(string $username)
{
$this->username = $username;
}
}
$users = [
new User('user 1'),
new User('user 2'),
new User('user 3'),
];
print_r(array_column($users, 'username'));
?>
以上示例将输出
Array ( [0] => user 1 [1] => user 2 [2] => user 3 )
示例 #4 使用魔术 __get() 方法从对象的私有“name”属性获取名称列。
<?php
class Person
{
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function __get($prop)
{
return $this->$prop;
}
public function __isset($prop) : bool
{
return isset($this->$prop);
}
}
$people = [
new Person('Fred'),
new Person('Jane'),
new Person('John'),
];
print_r(array_column($people, 'name'));
?>
以上示例将输出
Array ( [0] => Fred [1] => Jane [2] => John )
如果不存在 array_column,以下解决方案将起作用。
if(!function_exists("array_column"))
{
function array_column($array,$column_name)
{
return array_map(function($element) use($column_name){return $element[$column_name];}, $array);
}
}
如果您没有 array_column(),也可以使用 array_map 函数。
示例
$a = array(
array(
'id' => 2135,
'first_name' => 'John',
'last_name' => 'Doe',
),
array(
'id' => 3245,
'first_name' => 'Sally',
'last_name' => 'Smith',
)
);
array_column($a, 'last_name');
变为
array_map(function($element){return $element['last_name'];}, $a);
此函数不会保留数组的原始键(当不提供 index_key 时)。
您可以这样解决
<?php
// 不是
array_column($array, 'column');
// 保留键
array_combine(array_keys($array), array_column($array, 'column'));
?>
请注意,如果您使用 array_column 重置索引,当索引值为 null 时,在不同的 PHP 版本中会有不同的结果,示例
<?php
$array = [
[
'name' =>'Bob',
'house' =>'big',
],
[
'name' =>'Alice',
'house' =>'small',
],
[
'name' =>'Jack',
'house' => null,
],
];
var_dump(array_column($array,null,'house'));
在 5.6.30、7.0.0、7.2.0 (不限于)上获得以下结果
array(3) {
["big"]=>
array(2) {
["name"]=>
string(3) "Bob"
["house"]=>
string(3) "big"
}
["small"]=>
array(2) {
["name"]=>
string(5) "Alice"
["house"]=>
string(5) "small"
}
[0]=>
array(2) {
["name"]=>
string(4) "Jack"
["house"]=>
NULL
}
}
新索引,null 将被转换为 int,并且可以根据之前的索引递增,也就是说,如果 Alice "house" 也是 null,那么 Alice's 新索引是 "0", Jack's 新 索引是 "1"
在 7.1.21、7.2.18、7.4.8 (不限于)上将获得以下结果
array(3) {
["Big"]=>
array(2) {
["name"]=>
string(3) "Bob"
["house"]=>
string(3) "Big"
}
["small"]=>
array(2) {
["name"]=>
string(5) "Alice"
["house"]=>
string(5) "small"
}
[""]=>
array(2) {
["name"]=>
string(4) "Jack"
["house"]=>
NULL
}
}
新索引 null 将被转换为一个空字符串
官方文档中未包含的一些说明。
1) array_column 不支持一维数组,在这种情况下会返回一个空数组。
2) $column_key 是从 0 开始的。
3) 如果 $column_key 超出有效索引范围,则会返回一个空数组。
数组多列
<?php
function array_columns() {
$args = func_get_args();
$array = array_shift($args);
if (!$args) {
return $array;
}
$keys = array_flip($args);
return array_map(function($element) use($keys) {
return array_intersect_key($element, $keys);
}, $array);
}
?>
示例
<?php
$products = [
[
'id' => 2,
'name' => 'Phone',
'price' => 210.3
],
[
'id' => 3,
'name' => 'Laptop',
'price' => 430.12
]
];
print_r(array_columns($products, 'name', 'price'));
?>
输出
数组
(
[0] => 数组
(
[name] => Phone
[price] => 210.3
)
[1] => 数组
(
[name] => Laptop
[price] => 430.12
)
)
适用于多维数组(不仅仅是二维)的 array_column 实现
<?php
function array_column_recursive(array $haystack, $needle) {
$found = [];
array_walk_recursive($haystack, function($value, $key) use (&$found, $needle) {
if ($key == $needle)
$found[] = $value;
});
return $found;
}
取自 https://github.com/NinoSkopac/array_column_recursive
由于我的 PHP 版本中没有此函数,所以我编写了自己的版本,并根据我的需求对其进行了扩展。
当您为 `$indexkey` 赋值 -1 时,它会保留关联数组的键值。
示例
$sample = array(
'test1' => array(
'val1' = 10,
'val2' = 100
),
'test2' => array(
'val1' = 20,
'val2' = 200
),
'test3' => array(
'val1' = 30,
'val2' = 300
)
);
print_r(array_column_ext($sample,'val1'));
输出
数组
(
[0] => 10
[1] => 20
[2] => 30
)
print_r(array_column_ext($sample,'val1',-1));
输出
数组
(
['test1'] => 10
['test2'] => 20
['test3'] => 30
)
print_r(array_column_ext($sample,'val1','val2'));
输出
数组
(
[100] => 10
[200] => 20
[300] => 30
)
<?php
function array_column_ext($array, $columnkey, $indexkey = null) {
$result = array();
foreach ($array as $subarray => $value) {
if (array_key_exists($columnkey,$value)) { $val = $array[$subarray][$columnkey]; }
else if ($columnkey === null) { $val = $value; }
else { continue; }
if ($indexkey === null) { $result[] = $val; }
elseif ($indexkey == -1 || array_key_exists($indexkey,$value)) {
$result[($indexkey == -1)?$subarray:$array[$subarray][$indexkey]] = $val;
}
}
return $result;
}
?>
`array_column()` 的对应函数,即从列创建数组,可以使用 `array_map()` 来实现。
<?php
// 列
$lastnames = ['Skywalker', 'Organa', 'Kenobi'];
$firstnames = ['Luke', 'Leia', 'Obiwan'];
// 将列转换为数组
$characters = array_map(
fn ($l, $f) => ['lastname' => $l, 'firstname' => $f],
$lastnames, $firstnames
);
print_r($characters);
/*
[
0 => ['lastname' => 'Skywalker', 'firstname' => 'Luke']
1 => ['lastname' => 'Organa', 'firstname' => 'Leia']
2 => ['lastname' => 'Kenobi', 'firstname' => 'Obiwan']
]
*/
<?php
# 适用于 PHP < 5.5
# 并且适用于 ArrayObject 和对象数组
if (!function_exists('array_column')) {
function array_column($array, $columnKey, $indexKey = null)
{
$result = array();
foreach ($array as $subArray) {
if (is_null($indexKey) && array_key_exists($columnKey, $subArray)) {
$result[] = is_object($subArray)?$subArray->$columnKey: $subArray[$columnKey];
} elseif (array_key_exists($indexKey, $subArray)) {
if (is_null($columnKey)) {
$index = is_object($subArray)?$subArray->$indexKey: $subArray[$indexKey];
$result[$index] = $subArray;
} elseif (array_key_exists($columnKey, $subArray)) {
$index = is_object($subArray)?$subArray->$indexKey: $subArray[$indexKey];
$result[$index] = is_object($subArray)?$subArray->$columnKey: $subArray[$columnKey];
}
}
}
return $result;
}
}
?>
这是一个用于根据列值过滤记录集的小片段。
<?php
function dictionaryFilterList(array $source, array $data, string $column) : array
{
$new = array_column($data, $column);
$keep = array_diff($new, $source);
return array_intersect_key($data, $keep);
}
// 用法:
$users = [
['first_name' => 'Jed', 'last_name' => 'Lopez'],
['first_name' => 'Carlos', 'last_name' => 'Granados'],
['first_name' => 'Dirty', 'last_name' => 'Diana'],
['first_name' => 'John', 'last_name' => 'Williams'],
['first_name' => 'Betty', 'last_name' => 'Boop'],
['first_name' => 'Dan', 'last_name' => 'Daniels'],
['first_name' => 'Britt', 'last_name' => 'Anderson'],
['first_name' => 'Will', 'last_name' => 'Smith'],
['first_name' => 'Magic', 'last_name' => 'Johnson'],
];
var_dump(dictionaryFilterList(['Dirty', 'Dan'], $users, 'first_name'));
// 输出:
[
['first_name' => 'Jed', 'last_name' => 'Lopez'],
['first_name' => 'Carlos', 'last_name' => 'Granados'],
['first_name' => 'John', 'last_name' => 'Williams'],
['first_name' => 'Betty', 'last_name' => 'Boop'],
['first_name' => 'Britt', 'last_name' => 'Anderson'],
['first_name' => 'Will', 'last_name' => 'Smith'],
['first_name' => 'Magic', 'last_name' => 'Johnson']
]
?>
我为这里更受欢迎的答案添加了一些额外的功能,以支持 PHP < 5.5 的 `$index_key` 参数。
<?php
// 适用于 php < 5.5
if (!function_exists('array_column')) {
function array_column($input, $column_key, $index_key = null) {
$arr = array_map(function($d) use ($column_key, $index_key) {
if (!isset($d[$column_key])) {
return null;
}
if ($index_key !== null) {
return array($d[$index_key] => $d[$column_key]);
}
return $d[$column_key];
}, $input);
if ($index_key !== null) {
$tmp = array();
foreach ($arr as $ar) {
$tmp[key($ar)] = current($ar);
}
$arr = $tmp;
}
return $arr;
}
}
?>
请注意,当可能的键重复时,此函数将返回最后一个条目。
<?php
$array = array(
array(
'1-1',
'one',
'one',
),
array(
'1-2',
'two',
'one',
),
);
var_dump(array_column($array, $value = 0, $index = 1));
var_dump(array_column($array, $value = 0, $index = 2));
// 返回:
/*
array (size=2)
'one' => string '1-1' (length=3)
'two' => string '1-2' (length=3)
array (size=1)
'one' => string '1-2' (length=3)
*/
?>
//php < 5.5
if(function_exists('array_column'))
{
function array_column($arr_data, $col)
{
$result = array_map(function($arr){return $arr[$col]}, $arr_data);
return $result;
}
}
我的版本比 http://github.com/ramsey/array_column 更接近原始版本。
<?php
/**
* 为 PHP 5.5 之前的版本提供 array_column() 的功能。
* @copyright (c) 2015 WinterSilence (http://github.com/WinterSilence)
* @license MIT
*/
if (!function_exists('array_column')) {
/**
* 返回一个数组,该数组的值表示输入数组中的一列。
* @param array $array 一个多维数组,从中提取一列值。
* @param mixed $columnKey 要返回的值所在的列。此值可以是您想要检索的列的整数键,也可以是关联数组的字符串键名。它也可以是 NULL 以返回完整的数组(与 index_key 一起使用以重新索引数组)。
* @param mixed $indexKey 用作返回数组的索引/键的列。此值可以是列的整数键,也可以是字符串键名。
* @return array
*/
function array_column(array $array, $columnKey, $indexKey = null)
{
$result = array();
foreach ($array as $subArray) {
if (!is_array($subArray)) {
continue;
} elseif (is_null($indexKey) && array_key_exists($columnKey, $subArray)) {
$result[] = $subArray[$columnKey];
} elseif (array_key_exists($indexKey, $subArray)) {
if (is_null($columnKey)) {
$result[$subArray[$indexKey]] = $subArray;
} elseif (array_key_exists($columnKey, $subArray)) {
$result[$subArray[$indexKey]] = $subArray[$columnKey];
}
}
}
return $result;
}
}
?>
如果您想保留数组键,并且希望它同时适用于对象属性和数组元素,并且希望它在数组中的一些数组/对象未定义给定的键/属性时也能工作,基本上是您可以获得的最稳健的版本,但速度也足够快。
<?php
function array_column_keys(array|ArrayAccess $arr, string $col) {
// 类似 array_columns 但保留键
// 使其适用于对象和数组
return array_map(fn($e) => (is_countable($e) ? ($e[$col]??null) : null) ?: (is_object($e) ? $e->$col : null), $arr);
}
?>
如果键/属性未定义,则结果数组中的值为 NULL。如果需要,可以使用 array_filter() 过滤掉它们。
<?php
class a {
public string $a = 'property a';
public string $b = 'property b';
}
$a1 = new a;
$a2 = new a;
$a2->a = 'plop';
$b = ['one'=> ['a'=>'plop'],
3 => $a1,
4 => $a2,
5 =>[],
'kud'=>new a];
return array_column_keys($b, 'a');
?>
返回值
数组
(
[one] => plop
[3] => property a
[4] => 其他值
[5] =>
[kud] => property a
)
索引键仅在对应索引的值在整个数组中唯一时才能安全地应用。否则,只有具有相同索引键值的数组的最后一个元素会被提取。
<?php
$records = array(
array(
'id' => 2135,
'first_name' => 'John',
'last_name' => 'Doe',
'company_id' => 1,
),
array(
'id' => 3245,
'first_name' => 'Sally',
'last_name' => 'Smith',
'company_id' => 1,
),
array(
'id' => 5342,
'first_name' => 'Jane',
'last_name' => 'Jones',
'company_id' => 1,
),
array(
'id' => 5623,
'first_name' => 'Peter',
'last_name' => 'Doe',
'company_id' => 2,
)
);
$first_names = array_column($records, 'first_name', 'company_id');
print_r($first_names);
?>
以上示例将输出
<?php
Array
(
[1] => Jane
[2] => Peter
)
?>
要对数组中具有相同`index_key`的值进行分组,可以使用如下示例函数对`array_column`进行简单的替换
<?php
function arrayed_column(array $array, int|string $column_key, int|string $index_key) {
$output = [];
foreach ($array as $item) {
$output[$item['index_key']][] = $item['column_key'];
}
return $output;
}
$first_names = arrayed_column($records, 'first_name', 'company_id');
print_r($first_names);
?>
输出结果
<?php
Array
(
[1] => Array
(
[0] => John
[1] => Sally
[2] => Jane
)
[2] => Array
(
[0] =>Peter
)
)
?>
如果源数组中的条目没有 column_key 元素,则 array_column 会静默跳过该条目并返回一个比源数组短的数组。
如果条目无法通过 index_key 唯一标识,则无法确定哪些条目被跳过,因为如果没有 index_key,array_column 会返回一个普通列表。
<?php
$array = [
['a' => '0th', 'b' => 'zero'],
['a' => '1st', 'b' => 'one'],
['a' => '2nd' /* oops */],
['a' => '3rd', 'b'=>'three']];
var_export(array_column($array, 'b'));
var_export(array_column($array, 'b', 'a'));
?>
以下函数可能有助于从索引数组的所有值创建列
<?php
function array_column_all(array $arrays): array
{
$output = [];
$columnCount = count($arrays[0]);
for ($i = 0; $i < $columnCount; $i++)
{
$output [] = array_column($arrays, $i);
}
return $output;
}
?>
使用方法
-----
<?php
array_column_all(
[
['A1', 'A2', 'A3'],
['B1', 'B2', 'B3'],
['C1', 'C2', 'C3'],
]
);
?>
输出结果
-------------------
数组
(
[0] => 数组
(
[0] => A1
[1] => B1
[2] => C1
)
[1] => 数组
(
[0] => A2
[1] => B2
[2] => C2
)
[2] => 数组
(
[0] => A3
[1] => B3
[2] => C3
)
)
如果 (!function_exists('array_column'))
{
函数 array_column($input, $column_key=null, $index_key=null)
{
$result = array();
$i = 0;
foreach ($input as $v)
{
$k = $index_key === null || !isset($v[$index_key]) ? $i++ : $v[$index_key];
$result[$k] = $column_key === null ? $v : (isset($v[$column_key]) ? $v[$column_key] : null);
}
return $result;
}
}
一个简单的解决方案
function arrayColumn(array $array, $column_key, $index_key=null){
if(function_exists('array_column ')){
return array_column($array, $column_key, $index_key);
}
$result = [];
foreach($array as $arr){
if(!is_array($arr)) continue;
if(is_null($column_key)){
$value = $arr;
}else{
$value = $arr[$column_key];
}
if(!is_null($index_key)){
$key = $arr[$index_key];
$result[$key] = $value;
}else{
$result[] = $value;
}
}
return $result;
}
如果您需要从数组中提取多个列,您可以对每个元素使用 array_intersect_key,如下所示
function array_column_multi(array $input, array $column_keys) {
$result = array();
$column_keys = array_flip($column_keys);
foreach($input as $key => $el) {
$result[$key] = array_intersect_key($el, $column_keys);
}
return $result;
}
array_column() 将返回重复的值。
无需使用 array_unique(),只需将 $index_key 作为一种技巧。
**注意:当将 $column_key 和/或 $index_key 设置为整数时,这可能会变得很混乱。**
<?php
$records = [
[ 'id' => 2135, 'first_name' => 'John' ],
[ 'id' => 3245, 'first_name' => 'Sally' ],
[ 'id' => 5342, 'first_name' => 'Jane' ],
[ 'id' => 5623, 'first_name' => 'Peter' ],
[ 'id' => 6982, 'first_name' => 'Sally' ]
];
print_r(array_unique(array_column($records, 'first_name')));
// 强制唯一性,使键成为值。
print_r(array_column($records, 'first_name', 'first_name'));
print_r(array_column($records, 'id', 'first_name'));
// 返回
/*
数组
(
[0] => John
[1] => Sally
[2] => Jane
[3] => Peter
)
数组
(
[John] => John
[Sally] => Sally
[Jane] => Jane
[Peter] => Peter
)
数组
(
[John] => 2135
[Sally] => 6982
[Jane] => 5342
[Peter] => 5623
)
*/
?>
如果 array_column 不可使用,您可以使用以下函数,该函数也具有 $index_key 参数
if (!function_exists('array_column')) {
function array_column($array, $column_key, $index_key = null)
{
return array_reduce($array, function ($result, $item) use ($column_key, $index_key)
{
if (null === $index_key) {
$result[] = $item[$column_key];
} else {
$result[$item[$index_key]] = $item[$column_key];
}
return $result;
}, []);
}
}
如果要重新排列一个有两层(可能是来自数据库请求)的数组,则使用“array_walk”代替
<?php
$yamlList = [
['title' => 'hallo ich', 'identifier' => 'ich', 'Klaus'=> 'doof',],
['title' => 'hallo du', 'identifier' => 'du', 'Klaus'=> 'doof',],
['title' => 'hallo er', 'identifier' => 'er', 'Klaus'=> 'doof',],
];
echo ('Input'."\n".print_r($yamlList,true)."\n");
array_walk($yamlList, function (&$value, $key) {
$value = [
$value['title'],
$value['identifier'],
];
});
echo ("\n".'Output'."\n".print_r($yamlList,true)."\n");
?>
结果
===========
...
输出
数组
(
[0] => 数组
(
[0] => hallo ich
[1] => ich
)
[1] => 数组
(
[0] => hallo du
[1] => du
)
[2] => 数组
(
[0] => hallo er
[1] => er
)
)