Как преобразовать значения массива из строки в Int?

233
$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?

cwal
источник

Ответы:

537

Вы можете достичь этого с помощью следующего кода,

$integerIDs = array_map('intval', explode(',', $string));
Марк Бейкер
источник
3
но если у вас есть строка 'test', вы получите: array ([0] => 0)
Дмитрий Дубовицкий
10
@Dmitry - это верно .... это ответ на вопрос ОП, а не на 100% идеальный ответ в каждом конкретном случае на каждый потенциальный связанный вопрос. У OP была строка числовых значений, разделенных запятыми, а не набор текста и чисел
Марк Бейкер,
1
лучше использовать array_filter ($ array, 'is_numeric'), но он не может быть на 100% истинным, поскольку '0x539', '0b01011' - это числовые значения.
Дмитрий Дубовицкий
35
@Dmitry - если вы хотите критиковать 18-месячный ответ на конкретный вопрос, потому что он не идеален при всех возможных обстоятельствах, и думаете, что у вас есть лучшее решение, тогда не стесняйтесь добавлять свой ответ на этот вопрос, объясняя почему твой ответ лучше .... тебя никто не останавливает ... но оставь этот ответ таким, какой он есть
Марк Бейкер
intval () менее производительный, чем (int) приведение. Так что лучше используйте другое решение с (int). см. метод 3 здесь
Фабиан Пикон
43

Это почти в 3 раза быстрее , чем explode(), array_map()и intval():

$integerIDs = json_decode('[' . $string . ']', true);
sgrodzicki
источник
1
@Binod ваша строка, вероятно, синтаксическая ошибка. Он должен быть отформатирован так: $ string = "1,2,3";
sgrodzicki
4
explode () + array_map () + intval () может быть не так быстро, как json_decode (), но это явно не лучший вариант выбора ... вам нужно обрабатывать другие вещи, такие как ошибки синтаксиса json, которые вероятны, когда вы дезинфекция ввода пользователя
staabm
2
это ужасно, особенно когда это быстрее, чем карта + to_int! php, как это могло зайти так далеко ...
phoet
3
Это просто микрооптимизация. Нет необходимости оптимизировать такую ​​крошечную операцию, как приведение массива, заполненного строками, к целым числам. И если ваш массив содержит много-много элементов (например, сотни тысяч элементов), то в вашем проекте есть еще одна, гораздо более серьезная проблема, чем эта операция.
Андреас
1
@Andreas для меня не выглядит микрооптимизацией
sgrodzicki
41

Поэтому мне было интересно узнать о производительности некоторых методов, упомянутых в ответах для большого числа целых чисел.

подготовка

Просто создаю массив из 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)vs 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.

Изменить: Прошло много времени с тех пор, как ответ был первоначально опубликован. Чтобы уточнить, тест был сделан в php 5.6.

MikeWu
источник
1
Я действительно задаюсь вопросом, осталась ли производительность в PHP 7 такой же, и еще более любопытно, как бы сработал метод array_map массива 1 в сочетании с приведением метода 3 и закрытием / анонимным обратным вызовом ...
jave.web
array_map(function($v){ return (int)$v; }, $strings_array);это то, что я имел в виду
jave.web
Я сделал несколько тестов на PHP7.2, используя foreach (метод 1), array_map с 'intval' (метод 2) и array_map с анонимной функцией (метод 3) в массиве с 10000000 элементов. Я пришел к выводу, что мой метод 2 быстрее (~ 0,6 с), затем метод 3 (~ 0,75 с), затем метод 1 (~ 1,1 с)
Габриэль Лима
20

Используйте этот код с закрытием (введено в 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)
}
Andreas
источник
1
Согласно документу , это также быстрее, чем create_function, предложенный в других ответах.
до
1
@ пока Да, вы правы. И create_function устарела, начиная с PHP 7.2.0.
Андреас
14

В решении Марка вы вернетесь, array([0]=> int 0)если попытаетесь разобрать строку, например «test».

$integerIDs = array_map( 'intval', array_filter( explode(',', $string), 'is_numeric' ) );
Дмитрий Дубовицкий
источник
7

Не уверен, что это быстрее, но переворачивание массива дважды приведёт числовые строки к целым числам:

$string = "1,2,3, bla";
$ids = array_flip(array_flip(explode(',', $string)));
var_dump($ids);
baikho
источник
7

Альтернативный более короткий метод может быть:

$r = explode(',', $s);
foreach ($r as &$i) $i = (int) $i;

Он имеет ту же производительность, что и метод 3.

MyGeertRo
источник
самое короткое, но гибкое решение для меня.
Райан Ариф
5

Если у вас есть массив, как:

$runners = ["1","2","3","4"];

И если вы хотите преобразовать их в целые числа и оставить в массиве, выполните следующее:

$newArray = array_map( create_function('$value', 'return (int)$value;'),
            $runners);
star18bit
источник
create_function устарела с версии PHP 7.2.0. Лучше проверь мой ответ без create_function, но с анонимной функцией.
Андреас
4

Мое решение заключается в приведении каждого значения с помощью функции обратного вызова:

$ids = array_map( function($value) { return (int)$value; }, $ids )
Theva
источник
3

Будь проще...

$intArray = array ();
$strArray = explode(',', $string);
foreach ($strArray as $value)
$intArray [] = intval ($value);

Почему вы ищете другие пути? Цикл делает работу без боли. Если производительность вас беспокоит, вы можете пойти с json_decode (). Люди опубликовали, как использовать это, поэтому я не включаю это здесь.

Примечание. При использовании оператора == вместо === ваши строковые значения автоматически преобразуются в числа (например, целое или двойное), если они образуют действительное число без кавычек. Например:

$str = '1';
($str == 1) // true but
($str === 1) //false

Таким образом, == может решить вашу проблему, является эффективным, но сломается, если вы будете использовать === в сравнениях.

Дэвашиш джайсвал
источник
2

Если у вас есть многомерный массив, ни одно из ранее упомянутых решений не будет работать. Вот мое решение:

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]

(Это будет работать с любым уровнем глубины)

Skeets
источник
1

Вы можете конвертировать значения в массиве:

<?php

$ids = explode(',', $strings);
foreach ($ids as $index => $value) {
    $ids[$index] = (int)$value;
}

Вы также можете возвращать возвращаемое значение explodeфункции $stringsи повторять его вместо использования другой переменной ($ ids).

Я думаю, что это решение - самый безопасный способ с лучшей производительностью.

Рохам Рафи
источник
1

Стиль PHP 7.4:

$ids = array_map(fn(string $x): int => (int) $x, explode(',', $string));
Julien
источник
0

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)
}

Спасибо

Маной Кумар
источник