2013-02-18 82 views
3

我想将一个简单的多维数组变成一个更简单的数组。如何将一个简单的数组展平而不循环?

开启此:

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; 

我想做到这一点不用循环。你能帮我吗?

+4

为什么你想不做循环? – 2013-02-18 20:09:48

+0

最近有几个人发布关于数组和“不循环”我不明白为什么 - 他们可能不会 – 2013-02-18 20:11:39

+0

http://stackoverflow.com/questions/1319903/how-to-flatten-a-multidimensional-array – j08691 2013-02-18 20:11:44

回答

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

但是,没有任何理由不循环。没有真正的性能增益,并且可以减少代码的可读性。

+0

array_map循环:-) – 2013-02-18 20:12:00

+0

@Dagon'array_reduce'是否也循环? – 2013-02-19 03:03:51

+0

yup,while while循环 – 2013-02-19 03:15:43

5

我很佩服你希望有一些东西接近函数式编程和隐式循环,但PHP对你来说是错误的语言。它不能以功能性的风格自然表达自己。

reset函数返回第一个数组中的元素,这样就可以在阵列上映射该功能:

array_map('reset', $array) 

然而在PHP最快方法是一个简单的for环(未foreachfor)。这里有一些扁平化的不同方法。只有包含forforeach的函数执行显式循环并包含在内以进行比较。

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,PHP 5.3.15用了Suhosin贴片)我得到这些结果:

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, 
) 

在更长的阵列上,forforeach方法之间的差异较小。

令人惊讶的是(对我来说)flatten_merge仍然比普通的for循环慢。我预计array_merge_recursive的速度至少要快得多,因为它基本上把整个工作交给了C函数!

+0

如果您担心内部数组指针的状态,则可以使用'reset'而不是'current'。 – nickb 2013-02-18 20:33:48

+0

好主意。改变。 – 2013-02-18 20:35:39

+0

迷人。这非常有帮助。这个答案需要更多的赞扬!我期待着尽快在我自己的盒子上进行测试。 – Ryan 2013-02-19 01:33:26