Как преобразовать значения массива из строки в Int?
$string = "1,2,3"
$ids = explode(',', $string);
var_dump($ids);
возвращается
array(3) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
[2]=>
string(1) "3"
}
Мне нужно, чтобы значения были типа int вместо типа string. Есть ли лучший способ сделать это, чем цикл по массиву с foreach и преобразование каждой строки в int?
19 ответов
Поэтому мне было интересно узнать о производительности некоторых методов, упомянутых в ответах для большого числа целых чисел.
подготовка
Просто создаю массив из 1 миллиона случайных целых чисел от 0 до 100. Затем я сжал их, чтобы получить строку.
$integers = array();
for ($i = 0; $i < 1000000; $i++) {
$integers[] = rand(0, 100);
}
$long_string = implode(',', $integers);
Способ 1
Это один вкладыш из ответа Марка:
$integerIDs = array_map('intval', explode(',', $long_string));
Способ 2
Это подход JSON:
$integerIDs = json_decode('[' . $long_string . ']', true);
Способ 3
Я придумал это как модификацию ответа Марка. Это все еще использует explode()
функция, но вместо вызова array_map()
Я использую регулярный foreach
цикл, чтобы сделать работу, чтобы избежать накладных расходов array_map()
должно быть. Я также разбираюсь с (int)
против intval()
, но я пробовал оба, и нет большой разницы с точки зрения производительности.
$result_array = array();
$strings_array = explode(',', $long_string);
foreach ($strings_array as $each_number) {
$result_array[] = (int) $each_number;
}
Результаты:
Method 1 Method 2 Method 3
0.4804770947 0.3608930111 0.3387751579
0.4748001099 0.363986969 0.3762528896
0.4625790119 0.3645150661 0.3335959911
0.5065748692 0.3570590019 0.3365750313
0.4803431034 0.4135499001 0.3330330849
0.4510772228 0.4421861172 0.341176033
0.503674984 0.3612480164 0.3561749458
0.5598649979 0.352314949 0.3766179085
0.4573421478 0.3527538776 0.3473439217
0.4863037268 0.3742785454 0.3488383293
Суть в среднем. Похоже, что первый метод был немного медленнее для 1 миллиона целых чисел, но я не заметил 3-кратного увеличения производительности метода 2, как указано в ответе. Оказалось foreach
петля была самой быстрой в моем случае. Я сделал сравнительный анализ с Xdebug.
Это почти в 3 раза быстрее, чем explode()
, array_map()
а также intval()
:
$integerIDs = json_decode('[' . $string . ']', true);
Используйте этот код с закрытием (введено в PHP 5.3
), это немного быстрее, чем принятый ответ, и для меня намерение привести его к целому числу яснее:
// if you have your values in the format '1,2,3,4', use this before:
// $stringArray = explode(',', '1,2,3,4');
$stringArray = ['1', '2', '3', '4'];
$intArray = array_map(
function($value) { return (int)$value; },
$stringArray
);
var_dump($intArray);
Выход будет:
array(4) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
}
$integerIDs = array_map( 'intval', array_filter( explode(',', $string), 'is_numeric' ) );
В решении Марка вы вернетесь array([0]=> int 0)
если вы попытаетесь разобрать строку, такую как "тест".
Альтернативный более короткий метод может быть:
$r = explode(',', $s);
foreach ($r as &$i) $i = (int) $i;
Он имеет те же характеристики, что и метод 3.
Мое решение заключается в приведении каждого значения с помощью функции обратного вызова:
$ids = array_map( function($value) { return (int)$value; }, $ids )
Не уверен, что это быстрее, но переворачивание массива дважды приведёт числовые строки к целым числам:
$string = "1,2,3, bla";
$ids = array_flip(array_flip(explode(',', $string)));
var_dump($ids);
Стиль PHP 7.4:
$ids = array_map(fn(string $x): int => (int) $x, explode(',', $string));
Если у вас есть массив, как:
$runners = ["1","2","3","4"];
И если вы хотите преобразовать их в целые числа и не выходить за пределы массива, выполните следующие действия:
$newArray = array_map( create_function('$value', 'return (int)$value;'),
$runners);
Если у вас есть многомерный массив, ни одно из ранее упомянутых решений не будет работать. Вот мое решение:
public function arrayValuesToInt(&$array){
if(is_array($array)){
foreach($array as &$arrayPiece){
arrayValuesToInt($arrayPiece);
}
}else{
$array = intval($array);
}
}
Затем просто сделайте это:
arrayValuesToInt($multiDimentionalArray);
Это сделает массив следующим образом:
[["1","2"]["3","4"]]
выглядеть так:
[[1,2][3,4]
(Это будет работать с любым уровнем глубины)
Будь проще...
$intArray = array ();
$strArray = explode(',', $string);
foreach ($strArray as $value)
$intArray [] = intval ($value);
Почему вы ищете другие пути? Цикл делает работу без боли. Если производительность вас беспокоит, вы можете пойти с json_decode ()
, Люди опубликовали, как использовать это, поэтому я не включаю это здесь.
Примечание. При использовании оператора == вместо === ваши строковые значения автоматически преобразуются в числа (например, целые или двойные), если они образуют действительное число без кавычек. Например:
$str = '1';
($str == 1) // true but
($str === 1) //false
Таким образом, == может решить вашу проблему, является эффективным, но сломается, если вы будете использовать === в сравнениях.
$arr = ["adfsf", "*&^%$#^", "23", "25", "29"];
function convertArrayStringToArrayInt($arr)
{
$result = [];
foreach($arr as $value) {
if ((int)$value !== 0) {
$result[] = (int)$value;
}
}
return $result;
}
$result = convertArrayStringToArrayInt($arr);
var_dump($result);
Результат будет таким
array(3) {
[0]=> int(23)
[1]=> int(25)
[2]=> int(29)
}
Вы можете конвертировать значения в массиве:
<?php
$ids = explode(',', $strings);
foreach ($ids as $index => $value) {
$ids[$index] = (int)$value;
}
Вы также можете вернуть возвращаемое значение explode
функция к $strings
и итерируйте его вместо использования другой переменной ($ids).
Я думаю, что это решение - самый безопасный способ с лучшей производительностью.
<?php
$string = "1,2,3";
$ids = explode(',', $string );
array_walk( $ids, function ( &$id )
{
$id = (int) $id;
});
var_dump( $ids );
Я удивлен, что никто не предложил
filter_var
метод, я не уверен, насколько хорошо он работает с огромными наборами данных, но если ваш ключ важнее производительности, вот пример:
$sampleString = '1,2 3, 4, 6, 5 , a';
$filteredValues = filter_var(
explode(',', $sampleString),
FILTER_VALIDATE_INT,
FILTER_NULL_ON_FAILURE | FILTER_FORCE_ARRAY
);
array (size=6)
0 => int 1
1 => null
2 => int 4
3 => int 6
4 => int 5
5 => null
Как вы видете
2 3
не является допустимым числом, таким же, как
a
и были заменены на
null
Чтобы избавиться от пустых значений, вы можете применить
array_filter
$filteredValues = array_filter($filteredValues);
который даст следующий результат:
array (size=4)
0 => int 1
2 => int 4
3 => int 6
4 => int 5
У меня есть решение для некоторых читателей, я немного изменил решение мистера Марка Бейкера выше.
Для пользователей, имеющих проблемы с массивами, используйте Laravel PHP, вот настройка
$originalArray = $data->pluck('column')->toArray();
$convertedString = implode(', ', $originalArray);
$data = array_map('intval', explode(',', $convertedString ));
var_dump($data);
Input => '["3","6","16","120"]'
Я использовал преобразование типов => (int)$s;
function Str_Int_Arr($data){
$h=[];
$arr=substr($data,1,-1);
//$exp=str_replace( ",","", $arr);
$exp=str_replace( "\"","", $arr);
$s='';
$m=0;
foreach (str_split($exp) as $k){
if('0'<= $k && '9'>$k || $k =","){
if('0' <= $k && '9' > $k){
$s.=$k;
$h[$m]=(int)$s;
}else{
$s="";
$m+=1;
}
}
}
return $h;
}
var_dump(Str_Int_Arr('["3","6","16","120"]'));
Выход:
array(4) {
[0]=>
int(3)
[1]=>
int(6)
[2]=>
int(16)
[3]=>
int(120)
}
Благодарность
Другой метод заключается в том, чтобы указать (принуждать) входящие значения к
int
введите после разрыва строки.
Обратите внимание, что эти методы будут работать, как показано в моей демонстрационной ссылке, если вы не настроили php для использования строгой типизации.
Следующие методы не следует использовать для очистки нечисловых строк; предполагается, что все значения будут числовыми.
Если в эти методы передаются значения с плавающей запятой, они будут усечены / преобразованы в целые числа.
Код: ( Демо)
$string = "1,2,3";
$array = explode(',', $string);
var_dump($array);
echo "\n---\n";
array_walk($array, function(int &$int){;});
var_dump($array);
echo "\n---\n";
var_dump(
array_map(function(int $i){ return $i; }, explode(',', $string))
);
echo "\n---\n";
var_dump(
array_map(fn(int $i) => $i, explode(',', $string)) // PHP 7.4 arrow function syntax
);
Вывод:
array(3) {
[0]=> string(1) "1"
[1]=> string(1) "2"
[2]=> string(1) "3"
}
---
array(3) {
[0]=> int(1)
[1]=> int(2)
[2]=> int(3)
}
---
array(3) {
[0]=> int(1)
[1]=> int(2)
[2]=> int(3)
}
---
array(3) {
[0]=> int(1)
[1]=> int(2)
[2]=> int(3)
}