В настоящее время я оптимизирую приложение PHP и обнаружил, что одна функция вызывается примерно в 10-20 тыс. Раз, поэтому я подумал, что приступим к оптимизации:
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; }
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; 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; 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; }
с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; }
с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; }
Вам также может понадобиться lookup array_change_key_case ()
Я предполагаю, что вы не заботитесь о литье в массив …
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; } }
здесь пример использования лямбда:
$multiArrayChangeKeyCase = function (&$array) use (&$multiArrayChangeKeyCase) { $array = array_change_key_case($array); foreach ($array as $key => $row) if (is_array($row)) $multiArrayChangeKeyCase($array[$key]); };
array_combine(array_map("strtolower", array_keys($a)), array_values($a))