我想将一个简单的多维数组转换为更简单的数组。
转过来:
Array
(
[0] => Array
(
[id] => 123
)
[1] => Array
(
[id] => 456
)
...
[999] => Array
(
[id] => 789
)
)
进入这样的数组:
Array
(
[0] => 123
[1] => 456
...
[999] => 789
)
我想通过foreach
执行而不循环。这可能在PHP吗?
以下是我可以使用foreach
循环解决问题的方法:
$newArr = array();
foreach ($arr as $a) {
$newArr[] = $a['id'];
}
$arr = $newArr;
我想在没有循环的情况下这样做。你能帮忙吗?
答案 0 :(得分:5)
我很钦佩你希望有一些接近函数式编程和隐式循环的东西,但PHP对你来说是错误的语言。它并不以功能性的方式自然地表达出来。
reset
函数返回数组中的第一个元素,因此您可以在数组上映射该函数:
array_map('reset', $array)
然而,在PHP中,最快的方法是简单的for
循环(不是foreach
,for
)。这里有一堆不同的扁平化方法。只有包含for
和foreach
的函数才会执行显式循环,并包含在内进行比较。
function flatten_for($arr) {
$c = count($arr);
$newarr = array();
for ($i = 0; $i < $c; $i++) {
$newarr[] = $arr[$i][0];
}
return $newarr;
}
function flatten_for_inplace($arr) {
$c = count($arr);
for ($i = 0; $i < $c; $i++) {
$arr[$i] = $arr[$i][0];
}
}
function flatten_foreach($arr) {
$newarr = array();
foreach ($arr as $value) {
$newarr[] = $value[0];
}
return $newarr;
}
function flatten_foreach_inplace($arr) {
foreach ($arr as $k => $v) {
$arr[$k] = $v[0];
}
}
function flatten_foreach_inplace_ref($arr) {
foreach ($arr as &$value) {
$value = $value[0];
}
}
function flatten_map($arr) {
return array_map('reset', $arr);
}
function flatten_walk($arr) {
array_walk($arr, function(&$v, $k){$v = $v[0];});
}
function visitor($v, $k, &$a) {
return $a[] = $v;
}
function flatten_walk_recursive($arr) {
$newarr = array();
array_walk_recursive($arr, 'visitor', $newarr);
return $newarr;
}
function reducer($result, $item) {
return $item[0];
}
function flatten_reduce($arr) {
return array_reduce($arr, 'reducer', array());
}
function flatten_merge($arr) {
return call_user_func_array('array_merge_recursive', $arr);
}
这是时间码:
function buildarray($length) {
return array_map(function($e){return array($e);}, range(0, $length));
}
function timeit($callable, $argfactory, $iterations) {
$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
call_user_func($callable, call_user_func($argfactory));
}
return microtime(true) - $start;
}
function time_callbacks($callbacks, $argfactory, $iterations) {
$times = array();
foreach ($callbacks as $callback) {
$times[$callback] = timeit($callback, $argfactory, $iterations);
}
return $times;
}
function argfactory() {
return buildarray(1000);
}
$flatteners = array(
'flatten_for', 'flatten_for_inplace', 'flatten_foreach',
'flatten_foreach_inplace', 'flatten_foreach_inplace_ref',
'flatten_map', 'flatten_walk', 'flatten_walk_recursive',
'flatten_reduce', 'flatten_merge',
);
$results = time_callbacks($flatteners, 'argfactory', 1000);
var_export($results);
在旧版的MacBook Pro(Core 2 Duo,2.66 GHz,8GB,带有Suhosin-Patch的PHP 5.3.15)上,我得到了以下结果:
array (
'flatten_for' => 12.793387174606,
'flatten_for_inplace' => 14.093497991562,
'flatten_foreach' => 16.71691608429,
'flatten_foreach_inplace' => 16.964510917664,
'flatten_foreach_inplace_ref' => 16.618073940277,
'flatten_map' => 24.578175067902,
'flatten_walk' => 22.884744882584,
'flatten_walk_recursive' => 31.647840976715,
'flatten_reduce' => 17.748590946198,
'flatten_merge' => 20.691106081009,
)
for
和foreach
方法之间的差异在较长的数组上较小。
令人惊讶的是(无论如何)flatten_merge
仍然比普通for
循环慢。我希望array_merge_recursive
至少同样快,如果不是更快,因为它基本上把整个工作交给了C函数!
答案 1 :(得分:3)
你可以map
:
$arr = array_map(function($element) {
return $element['id'];
}, $arr);
由于array_map
可能在内部循环,所以你可以在没有循环的情况下真正做到这一点:
$arr = array_reduce($arr, function($arr, $element) {
$arr[] = $element['id'];
return $arr;
});
但是没有理由不循环。没有真正的性能提升,代码的可读性可以降低。
答案 2 :(得分:0)
目前,最简单的方法是使用array_column()函数
$newArray = array_column($array, 'id');