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