我有一个数组,它由数量不确定的数组组成,递归(n级深)。每个数组可能包含一个name
密钥。我想创建一个这些值的唯一列表。
示例
假设数组为:
$bigArray = array(
'name'=>'one',
'something'=>array(
'name'=>'two',
'subthing'=>array('name'=>'three')
),
'anotherthing'=>array('name'=>'one')
);
预期结果是:
$uniques = array('one', 'two', 'three') // All the 'name' keys values and without duplicates.
这是我尝试的一把小提琴。
我的方法是使用array_walk_recursive
传递$uniques
数组作为引用,并允许函数更新该值:
$uniques = array();
function singleOut($item, $key, &$uniques) {
if ($key == 'name' && !in_array($itm,$uniques,true) )
$uniques[] = $item;
}
array_walk_recursive($bigArray, 'singleOut', $uniques);
但是,它对我不起作用。
您也可以在这个上使用array_unique
。示例:
$uniques = array();
array_walk_recursive($bigArray, function($val, $key) use (&$uniques){
if($key == 'name') {
$uniques[] = $val;
}
});
$uniques = array_unique($uniques); // unique values
你的fiddle几乎是对的——问题是,用户参数只在相同级别的递归中通过引用给出。您需要使用间接引用:
$bigArray = array(
'name'=>'one',
'something'=>array(
'name'=>'two',
'subthing'=>array('name'=>'three')
),
'anotherthing'=>array('name'=>'one')
);
function singleOut($item, $key, $indirect) {
$uniques=&$indirect[0];
if ($key == 'name' && !in_array($item,$uniques,true) ) $uniques[] = $item;
}
$uniques = array();
$indirect = array(&$uniques);
array_walk_recursive($bigArray, 'singleOut', $indirect);
print_r($uniques);
编辑:
Fiddle在这里
为了避免在array_walk_recursive()
内部进行in_array()
检查,可以将name
值存储为输出数组中的键。这将通过覆盖以前相同的密钥来有效地消除重复。array_walk_recursive()
完成后,可以使用array_keys()
将数据从键移动到值。
代码:(演示)
$bigArray=[
'name'=>'one',
'something'=>[
'name'=>'two',
'subthing'=>['name'=>'three']
],
'anotherthing'=>['name'=>'one']
];
array_walk_recursive($bigArray,function($v,$k)use(&$uniques){
if($k==='name')
$uniques[$v]='';
});
var_export(array_keys($uniques));
输出:
array (
0 => 'one',
1 => 'two',
2 => 'three',
)
由于array_unique()
在某些情况下可能很慢,因此使用array_keys()
通常应该执行得更快。也就是说,如果微观优化是一个问题,那么你应该使用你的实际数据和特定环境进行基准测试,并为你的项目选择最佳方法。
正如我在Ghost的回答下的一条评论中提到的,对多维数组中的键进行===
严格比较是一个好习惯,因为如果你正在寻找一个字符串,但遇到了0
键,那么PHP的类型转换"功能"会提供意想不到的结果。
这是一个我讨论和演示这种行为的页面:在进行松散比较时进行类型杂耍会产生不想要的结果