2010-06-05 68 views
3

我目前优化PHP应用程序,发现一个功能周围10-20K次被调用,所以我想我会那里开始优化:键转换为小写

function keysToLower($obj) 
{ 
     if(!is_object($obj) && !is_array($obj)) return $obj; 
     foreach($obj as $key=>$element) 
     { 
       $element=keysToLower($element); 
       if(is_object($obj)) 
       { 
         $obj->{strtolower($key)}=$element; 
         if(!ctype_lower($key)) unset($obj->{$key}); 
       } 
       else if(is_array($obj) && ctype_upper($key)) 
       { 
         $obj[strtolower($key)]=$element; 
         unset($obj[$key]); 
       } 
     } 
     return $obj; 
} 

大部分时间都花在递归调用中(这在PHP中很慢),但我没有看到任何将它转换为循环的方法。 你会做什么?

该版本没有考虑关联数组,因为我的数据没有任何数据,但速度比原始版本快近10倍。大部分工作都由Gumbo完成,主要的加速来自于使用引用和创建新对象,而不是取消旧密钥的设置。

function &keysToLower(&$obj) 
{ 
    if(is_object($obj)) 
    { 
     $newobj = (object) array(); 
     foreach ($obj as $key => &$val) 
      $newobj->{strtolower($key)} = keysToLower($val); 
     $obj=$newobj; 
    } 
    else if(is_array($obj)) 
     foreach($obj as &$value) 
      keysToLower($value); 
    return $obj; 
} 
+0

您总是可以使用辅助堆栈轻松删除递归调用。 – Artefacto 2010-06-05 18:16:56

+0

我建议array_walk_recursive,但删除了我的帖子 - 我不能轻易地让它做你想做的事,尽管你可能想自己看看这个功能。 – Erik 2010-06-05 18:18:53

+0

显然array_walk_recursive不会考虑使用回调函数创建的元素。 – tstenner 2010-06-05 18:29:20

回答

4

Foreach使用一个内部复制,然后将其穿过。尝试没有:

function keysToLower($obj) 
{ 
    $type = (int) is_object($obj) - (int) is_array($obj); 
    if ($type === 0) return $obj; 
    reset($obj); 
    while (($key = key($obj)) !== null) 
    { 
     $element = keysToLower(current($obj)); 
     switch ($type) 
     { 
     case 1: 
      if (!is_int($key) && $key !== ($keyLowercase = strtolower($key))) 
      { 
       unset($obj->{$key}); 
       $key = $keyLowercase; 
      } 
      $obj->{$key} = $element; 
      break; 
     case -1: 
      if (!is_int($key) && $key !== ($keyLowercase = strtolower($key))) 
      { 
       unset($obj[$key]); 
       $key = $keyLowercase; 
      } 
      $obj[$key] = $element; 
      break; 
     } 
     next($obj); 
    } 
    return $obj; 
} 

或者使用引用,以避免一个副本用于:

function &keysToLower(&$obj) 
{ 
    $type = (int) is_object($obj) - (int) is_array($obj); 
    if ($type === 0) return $obj; 
    foreach ($obj as $key => &$val) 
    { 
     $element = keysToLower($val); 
     switch ($type) 
     { 
     case 1: 
      if (!is_int($key) && $key !== ($keyLowercase = strtolower($key))) 
      { 
       unset($obj->{$key}); 
       $key = $keyLowercase; 
      } 
      $obj->{$key} = $element; 
      break; 
     case -1: 
      if (!is_int($key) && $key !== ($keyLowercase = strtolower($key))) 
      { 
       unset($obj[$key]); 
       $key = $keyLowercase; 
      } 
      $obj[$key] = $element; 
      break; 
     } 
    } 
    return $obj; 
} 
+0

就可以正常工作除了没有键的嵌套数组之外,第二级的每个数组都是空的。 'keyToLower(array(array(1,2))))'''array'(0 => array())' – tstenner 2010-06-05 18:55:30

+0

'if($ key!== $ keyLowercase)'可以防止数组中的值小写键被处理,例如'array('lowercase'=> array('UPPERCASE'=> 1))'不起作用。 插入'else $ val = keysToLower($ val);'修复此问题。 – tstenner 2010-06-05 18:58:34

+0

如果($ key!== $ keyLowercase &&!ctype_digit($ keyLowercase)'' – tstenner 2010-06-05 19:09:02

1
array_combine(array_map("strtolower", array_keys($a)), array_values($a)) 
+1

不会递归,但可能是加速他的代码的好开始 – Erik 2010-06-05 18:25:53

+0

适用于数组,但不适用于对象。 – tstenner 2010-06-05 18:31:06

+1

纠正:只要你使用'(array)$ a'投射数组,只要你使用'(array)$ a' – tstenner 2010-06-05 18:37:05

2

我以为你不关心铸造阵列...

function keys_to_lower($o) { 
    if (is_object($o)) { 
     $o = (array)$o; 
    } 
    if (is_array($o)) { 
     return array_map('keys_to_lower', array_change_key_case($o)); 
    } 
    else { 
     return $o; 
    } 
} 
+0

我很在乎,但是我会测量,是否这样做并在返回之前重新进行重新设定 – tstenner 2010-06-05 20:20:55

2

这里使用lambda的一个例子:

$multiArrayChangeKeyCase = function (&$array) use (&$multiArrayChangeKeyCase) { 
    $array = array_change_key_case($array); 

    foreach ($array as $key => $row) 
     if (is_array($row)) 
      $multiArrayChangeKeyCase($array[$key]); 
}; 
3

你也可能想要查找array_change_key_case()

+0

它只适用于数组 – zoom 2015-02-05 10:59:22

+0

@leoganda你可以使用($ obj)array_change_key_case((arr)$ o) – gaborous 2015-02-17 15:06:27