【问题标题】:Fastest way to add prefix to array keys?向数组键添加前缀的最快方法?
【发布时间】:2010-04-09 13:01:46
【问题描述】:

向数组键添加字符串前缀的最快方法是什么?

输入

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

需要的输出:

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

【问题讨论】:

    标签: php arrays


    【解决方案1】:

    我想可以用一长串来做到这一点:

    $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() 设置为第二个参数。如果你只是把数组扔进去,它无论如何都会使用这个值。
    • 漂亮的解决方案!
    【解决方案2】:
    function keyprefix($keyprefix, Array $array) {
    
        foreach($array as $k=>$v){
            $array[$keyprefix.$k] = $v;
            unset($array[$k]);
        }
    
        return $array; 
    }
    

    使用array_flip 不会保留空值或空值。 万一前缀键已经存在,可以添加额外的代码。

    【讨论】:

      【解决方案3】:

      另一种使用箭头函数语法编写@Lode's first snippet的方法,可从php7.4+获得:

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

      【讨论】:

        【解决方案4】:

        我发现 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

        【讨论】:

        • 这有点奇怪,因为我得到的值要低 10 倍:0.043029069900513。你知道为什么会这样吗?它是 PHP 5.4.3。如果我只为一个 foreach 而不是更长的脚本运行它,那么它是:6.4849853515625E-5
        • 他们似乎对我来说是正确的:codepad.viper-7.com/b1gHRC。 Foreach 仍然是明显的赢家。
        • 是的,foreach 是赢家,但我想知道为什么这个网站显示 0.0497624 和我的网站,使用完全相同的脚本显示 0.0000871
        • 听起来你的错字导致它无法正常运行。
        • 或者你有不同规格的不同主机..?
        【解决方案5】:
        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);
            }
        

        这已经实现并且运行良好

        【讨论】:

          【解决方案6】:

          如果你不想使用 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 会在内部使用一个循环,这里还有函数调用开销。

          【讨论】:

          • 在工作时,与 for 循环相比,这慢得令人难以置信,不是吗?
          • 你不应该使用引用。这实际上比传递和返回它更慢,更密集。找不到真正快速的文档。
          【解决方案7】:

          实现的另一种方法是使用 array_flip()

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

          【讨论】:

          • 如果数组中有相同的值,则选择错误
          【解决方案8】:

          我会创建一个全新的数组,并创建您的新密钥。 这必须比取消设置所有不需要的键更快;

          $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(...)kanWiki
          【解决方案9】:

          这是一种使用 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);
          

          【讨论】:

            【解决方案10】:

            我想出了一条线的解决方案:

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

            【讨论】:

            • 这不起作用。键没有改变。这与我在一个小时的大部分时间里一直在尝试做的事情相同:codepad.org/h88Is8ug
            猜你喜欢
            • 1970-01-01
            • 2017-10-30
            • 1970-01-01
            • 1970-01-01
            • 2013-06-11
            • 2013-05-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多