Поскольку «SELECT» MYSQL выбирает целые числа и плавает как строки, и мне нужен каждый ответ, который я получаю (от JS), чтобы быть в правильной модели данных –
Я создал эту рекурсивную функцию, которая работает с смешанным типом-массивом / объектом:
private function cast_number(&$mixed) { if(is_array($mixed)) { foreach ($mixed as $key => $val) if (is_numeric($val)) $mixed[$key] = (double)$val; else if (is_array($val) || is_object($val)) $mixed[$key] = $this->cast_number($val); } else if(is_object($mixed)) { foreach ($mixed as $key => $val) if (is_numeric($val)) $mixed->$key = (double)$val; else if (is_array($val) || is_object($val)) $mixed->$key = $this->cast_number($val); } return $mixed; }
Довольно простая функция – если это число, двойное, если массив или объект, переходите рекурсивно.
Все здесь на месте.
У меня есть две проблемы с этим: – На 6 Мбайтах данных, в основном числа, которые представлены в виде строк, потребовалось 0,5 секунды – на 200 МБ данных (да, мне это нужно, пожалуйста, не сосредотачивайтесь на нем), он не удался после пару минут (обычно секунд), говоря, что ему требуется более 4 ГБ памяти.
Поскольку принуждение использовалось быстрее, чем литье , я запускал этот код для вычисления таймингов на PHP 7:
function getTime($start) { return round((microtime(true) - $start) * 1000000) / 1000; } function mockData($length) { $data = []; $i = -1; while ($i++ < $length) { $data[$i] = strval(rand(1, 10000) / 100); } return $data; } $data = mockData(100000); // Let's check that they are string before echo gettype($data[0]) . '<br><br>'; $start = microtime(true); $convertedData = []; foreach ($data as $key => $value) { $convertedData[$key] = (double) $value; } echo '(double) cast took ' . getTime($start) . ' ms.<br>'; $start = microtime(true); $convertedData = []; foreach ($data as $key => $value) { $convertedData[$key] = 0 + $value; } echo 'Coercion took ' . getTime($start) . ' ms.<br>';
И мои результаты:
(double) cast took 27.508 ms. Coercion took 28.789 ms.
ВЫВОД
Поскольку использование floatval
(третий способ для преобразования строк в двойное преобразование) еще длиннее, вы не можете сделать лучше, чем с PHP. То, что вы пытаетесь достичь, – это сценарирование, оно не должно использоваться как обычная операционная система для веб-приложения.
Но если вы все еще хотите это сделать, вы можете memory_limit
свой memory_limit
внутри вашего файла php.ini
, если вы не используете обходной путь -1
.
ОБНОВИТЬ
Я забыл одну возможную оптимизацию, вы должны передать свою переменную по ссылке, чтобы хотя бы выполнить немедленную переадресацию:
$start = microtime(true); foreach ($data as $key => $value) { $data[$key] = (double) $value; } echo getTime($start) . ' ms.<br>';
=> 34,018 мс.
$start = microtime(true); foreach ($data as &$value) { $value = (double) $value; } echo getTime($start) . ' ms.<br>';
=> 17.081 мс.
И, по-видимому, использование принуждения со ссылкой дает еще лучшие результаты:
$start = microtime(true); foreach ($data as &$value) { $value = 0 + $value; } echo getTime($start) . ' ms.<br>';
=> 13,1 мс.
Это должно улучшить скорость и память:
private function cast_number(&$mixed) { foreach ($mixed as &$val) { if (is_numeric($val)) { $val = (double) $val; } else if (is_array($val) || is_object($val)) { $this->cast_number($val); } } // do not return $mixed }
но, возможно, вы можете добиться больших улучшений с помощью функции array_walk_recursive .