【发布时间】:2010-04-09 13:01:46
【问题描述】:
向数组键添加字符串前缀的最快方法是什么?
输入
$array = array(
'1' => 'val1',
'2' => 'val2',
);
需要的输出:
$array = array(
'prefix1' => 'val1',
'prefix2' => 'val2',
);
【问题讨论】:
向数组键添加字符串前缀的最快方法是什么?
输入
$array = array(
'1' => 'val1',
'2' => 'val2',
);
需要的输出:
$array = array(
'prefix1' => 'val1',
'prefix2' => 'val2',
);
【问题讨论】:
我想可以用一长串来做到这一点:
$array = array_combine(
array_map(function($k){ return 'prefix'.$k; }, array_keys($array)),
$array
);
或者对于 5.3 之前的 PHP 版本:
$array = array_combine(
array_map(create_function('$k', 'return "prefix".$k;'), array_keys($array)),
$array
);
可能有很多方法可以做到这一点:
foreach ($array as $k => $v)
{
$array['prefix_'.$k] = $v;
unset($array[$k]);
}
【讨论】:
array_values() 的array_map() 设置为第二个参数。如果你只是把数组扔进去,它无论如何都会使用这个值。
function keyprefix($keyprefix, Array $array) {
foreach($array as $k=>$v){
$array[$keyprefix.$k] = $v;
unset($array[$k]);
}
return $array;
}
使用array_flip 不会保留空值或空值。
万一前缀键已经存在,可以添加额外的代码。
【讨论】:
另一种使用箭头函数语法编写@Lode's first snippet的方法,可从php7.4+获得:
function prefixArrayKeys($array, $prefix) {
return array_combine(
array_map(fn($k) => $prefix . $k, array_keys($array)),
$array
);
}
【讨论】:
我发现 PHPBench 对于重要的基准测试来说并不是一个很好的来源。因此,除非您真的对运行 for(....); 感兴趣,否则它不会正确显示哪种语法会更快。我整理了一个简单的基准来证明当您在迭代期间同时使用键和值时,foreach 实际上是最快的。
实际上强制 PHP 从循环迭代中读取值非常重要,否则它会尽力优化它们。在下面的示例中,我使用doNothing 函数强制 PHP 每次都计算键和值。使用 doNothing 会导致对每个循环应用开销,但每个循环的开销都是相同的,因为调用次数相同。
foreach 排名第一我并不感到惊讶,因为它是用于迭代字典的语言结构。
$array = range( 0, 1000000 );
function doNothing( $value, $key ) {;}
$t1_start = microtime(true);
foreach( $array as $key => $value ) {
doNothing( $value, $key );
}
$t1_end = microtime(true);
$t2_start = microtime(true);
$array_size = count( $array );
for( $key = 0; $key < $array_size; $key++ ) {
doNothing( $array[$key], $key );
}
$t2_end = microtime(true);
//suggestion from PHPBench as the "fastest" way to iterate an array
$t3_start = microtime(true);
$key = array_keys($array);
$size = sizeOf($key);
for( $i=0; $i < $size; $i++ ) {
doNothing( $key[$i], $array[$key[$i]] );
}
$t3_end = microtime(true);
$t4_start = microtime(true);
array_walk( $array, "doNothing" );
$t4_end = microtime(true);
print
"Test 1 ".($t1_end - $t1_start)."\n". //Test 1 0.342370986938
"Test 2 ".($t2_end - $t2_start)."\n". //Test 2 0.369848966599
"Test 3 ".($t3_end - $t3_start)."\n". //Test 3 0.78616809845
"Test 4 ".($t4_end - $t4_start)."\n"; //Test 4 0.542922019958
编辑:我在 64 位 Mac OSX 10.6 上使用 PHP 5.3
【讨论】:
0.043029069900513。你知道为什么会这样吗?它是 PHP 5.4.3。如果我只为一个 foreach 而不是更长的脚本运行它,那么它是:6.4849853515625E-5
0.0497624 和我的网站,使用完全相同的脚本显示 0.0000871。
function array_key_prefix_suffix(&$array,$prefix='',$suffix=''){
$key_array = array_keys($array);
$key_string = $prefix.implode($suffix.','.$prefix,$key_array).$suffix;
$key_array = explode(',', $key_string);
$array = array_combine($key_array, $array);
}
这已经实现并且运行良好
【讨论】:
如果你不想使用 for 循环,你可以这样做:
// function called by array_walk to change the $value in $key=>$value.
function myfunction(&$value,$key) {
$value="prefix$value";
}
$keys = array_keys($array); // extract just the keys.
array_walk($keys,"myfunction"); // modify each key by adding a prefix.
$a = array_combine($keys,array_values($array)); // combine new keys with old values.
我认为这不会比for 循环更有效。我猜 array_walk 会在内部使用一个循环,这里还有函数调用开销。
【讨论】:
实现的另一种方法是使用 array_flip()
<?php
$data = array_flip($data);
foreach($data as $key => &$val) { $val = "prefix" . $val; }
$data = array_flip($data);
【讨论】:
我会创建一个全新的数组,并创建您的新密钥。 这必须比取消设置所有不需要的键更快;
$prefixed_array = array();
foreach ($array as $key => $value) {
$prefixed_array[ $prefix . $key] = $value;
}
如果你想做任何其他的“词缀”
function array_affix_keys($affix, Array $array, $type = 'prefix', $options = array()){
$affixed_array = array();
if($type =='prefix'){
foreach ($array as $key => $value) {$affixed_array[ $affix . $key] = $value;}
return $affixed_array;
}
if($type =='suffix'){
foreach ($array as $key => $value) {$affixed_array[$key . $affix ] = $value;}
return $affixed_array;
}
if($type =='circumfix'){
if(is_array($affix) && count($affix) == 2){
foreach ($array as $key => $value) {
$affixed_array[ $affix[0] . $key . $affix[1] ] = $value;
}
}
return $affixed_array;
}
if($type == 'simulfix' && isset($options['phonemes'])){
foreach ($array as $key => $value) { $affixed_array[ str_replace($options['phonemes'], $affix, $key) ] = $value;}
return $affixed_array;
}
return $array;
}
$prefixed = array_affix_keys('prefix_', $array);
$prefixed = array_affix_keys('prefix_', $array, 'prefix');
$suffixed = array_affix_keys('_suffix', $array, 'suffix');
$circumfixed = array_affix_keys(array('prefix', 'suffix'), $array, 'circumfix');
$simulfix = array_affix_keys('replace', $array, 'simulfix', array('phonemes' => 'find'));
【讨论】:
circumfix 的这个实现是错误的。 Circumfix 的结尾与开头不同,例如per(...)kan。 Wiki
这是一种使用 implode / explode 添加前缀和/或后缀的快速单行解决方案(PHP 4+ 支持):
$array = range(0, 1000000);
$delimiter = '-';
$prefix = 'string';
$suffix = '';
$result = array_combine(explode($delimiter, $prefix . implode($suffix . $delimiter . $prefix, array_keys($array)) . $suffix), $array);
【讨论】:
我想出了一条线的解决方案:
array_walk($array, create_function('$value, &$key', '$key = "prefix" . $key;'));
【讨论】: