Подтвердить что ты не робот

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

Каков самый быстрый способ добавить строковые префиксы к клавишам массива?

Ввод

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

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

$array = array(
  'prefix1' => 'val1',
  'prefix2' => 'val2',
);
4b9b3361

Ответ 1

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

Изменить: я использую PHP 5.3 на 64-разрядной Mac OSX 10.6

Ответ 2

Можно сделать это в одной длинной строке, которую я предполагаю:

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

Ответ 3

function keyprefix($keyprefix, Array $array) {

    foreach($array as $k=>$v){
        $array[$keyprefix.$k] = $v;
        unset($array[$k]);
    }

    return $array; 
}

Использование array_flip не будет сохранять пустые или нулевые значения. Дополнительный код можно добавить в маловероятном случае, когда ключ с префиксом уже существует.

Ответ 4

Если вы не хотите использовать цикл 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 будет внутренне использовать цикл, и здесь также есть служебные вызовы функции.

Ответ 5

Еще один способ добиться - с помощью array_flip()

<?php 
    $data = array_flip($data);
    foreach($data as $key => &$val) { $val = "prefix" . $val; }
    $data = array_flip($data);

Ответ 6

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

Это реализовано и работает очень хорошо

Ответ 7

Я бы создал совершенно новый массив и создал новые ключи. Это должно быть быстрее, чем устранение всех нежелательных клавиш;

$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'));

Ответ 8

Вот быстрое решение, состоящее из одной строки (поддерживаемое в PHP 4+) для добавления префикса и/или суффикса с помощью команды implode/explode:

$array = range(0, 1000000);
$delimiter = '-';
$prefix = 'string';
$suffix = '';

$result = array_combine(explode($delimiter, $prefix . implode($suffix . $delimiter . $prefix, array_keys($array)) . $suffix), $array);

Ответ 9

Я понял однострочное решение:

array_walk($array, create_function('$value, &$key', '$key = "prefix" . $key;'));