як перетворити значення масиву з рядка в 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 замість рядка типу. Чи є кращий спосіб зробити це, ніж прокручувати масив з допомогою foreach і перетворювати кожну рядок в int?

Відповіді:


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 тут
Fabian Picone

43

Це майже в 3 рази швидше , ніж explode(), array_map()і intval():

$integerIDs = json_decode('[' . $string . ']', true);

1
@Binod у вашому рядку є, мабуть, помилка синтаксису. Він повинен бути відформатований так: $ string = "1,2,3";
sgrodzicki

4
explode () + array_map () + intval () може бути не настільки швидким, як json_decode (), але це, очевидно, не кращий варіант вибору ... вам потрібно обробляти інші речі, такі як помилки синтаксису json, які, ймовірно, є
санітація

2
це жахливо, особливо коли це швидше, ніж карта + to_int! php, як це могло зайти так далеко ...
phoet

3
Це просто мікрооптимізація. Не потрібно оптимізувати таку крихітну операцію, як передача масиву, наповненого рядками, до цілих чисел. І якщо ваш масив містить багато і багато елементів (наприклад, сотні тисяч елементів), то у вашому проекті є ще одна, набагато більша проблема, ніж ця операція.
Андреас

1
@Andreas не виглядає як мікро оптимізації для мене: blackfire.io/profiles/compare / ...
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)vsintval() , але я спробував і те, і інше, і щодо продуктивності немає великої різниці.

  $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.


1
Мені дійсно цікаво, чи продуктивність залишилася такою ж у PHP 7, і ще цікавіше, як би зробив метод 1 array_map у поєднанні з методом 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,6s), потім метод 3 (~ 0,75s), потім метод 1 (~ 1,1s)
Габріель Ліма

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

1
За словами документа , це також швидше, ніж create_function, запропонований в інших відповідях.
до

1
@untill Так, ви праві. А create_function застаріла з PHP 7.2.0.
Андреас

14

У рішення Марка ви повернетесь, array([0]=> int 0)якщо спробуєте розібрати рядок типу "тест".

$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);

7

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

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

Він має таку ж ефективність, як і метод 3.


найкоротше, але гнучке рішення для мене.
Ryan Arief

5

Якщо у вас є масив типу:

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

І якщо ви хочете їх перетворити в цілі числа і зберегти в масиві, слід виконати цю роботу:

$newArray = array_map( create_function('$value', 'return (int)$value;'),
            $runners);

create_function застаріла з PHP 7.2.0. Краще перевірити мою відповідь без create_function, але з анонімною функцією.
Андреас

4

Моє рішення - це перерахування кожного значення за допомогою функції зворотного виклику:

$ids = array_map( function($value) { return (int)$value; }, $ids )

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]

(Це буде працювати з будь-яким рівнем глибини)


1

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

<?php

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

Ви також можете повернути значення повернення explodeфункції$strings та повторити її замість використання іншої змінної ($ ids).

Я думаю, що це рішення - це найбезпечніший спосіб із найкращими показниками.



0

Вхідні дані => '["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)
}

Дякую

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.