Самый быстрый способ добавить префикс к ключам массива?

Что самый быстрый путь состоит в том, чтобы добавить строковые префиксы к ключам массива?

Вход

$array = array(
 '1' => 'val1',
 '2' => 'val2',
);

Необходимый вывод:

$array = array(
  'prefix1' => 'val1',
  'prefix2' => 'val2',
);
35
задан hakre 18 December 2012 в 20:27
поделиться

3 ответа

Я обнаружил, что 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

Edit: I'm using PHP 5.3 on 64-bit Mac OSX 10.6

11
ответ дан 27 November 2019 в 06:51
поделиться

Я полагаю, это можно сделать одной длинной строкой:

$array = array_combine(
    array_map(function($k){ return 'prefix'.$k; }, array_keys($array)),
    $array
);

Или для версий PHP до 5.3:

$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]);
}
58
ответ дан 27 November 2019 в 06:51
поделиться

Если вы не хотите использовать цикл 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.

Я не думаю, что это будет более эффективно, чем для цикла . Я предполагаю, что array_walk будет внутренне использовать цикл, и здесь также есть накладные расходы на вызов функции.

2
ответ дан 27 November 2019 в 06:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: