310

The following code:

$string = "1,2,3"
$ids = explode(',', $string);
var_dump($ids);

Returns the array:

array(3) {
  [0]=>
  string(1) "1"
  [1]=>
  string(1) "2"
  [2]=>
  string(1) "3"
}

I need for the values to be of type int instead of type string. Is there a better way of doing this than looping through the array with foreach and converting each string to int?

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
cwal
  • 3,732
  • 3
  • 19
  • 20
  • 1
    For researchers looking for a solution that is suited to multidimensional data, please see this similar question: https://stackoverflow.com/questions/27147105/php-convert-string-in-array-to-int – mickmackusa Oct 14 '20 at 03:02

17 Answers17

717

You can achieve this by following code,

$integerIDs = array_map('intval', explode(',', $string));
Rahul
  • 18,271
  • 7
  • 41
  • 60
Mark Baker
  • 209,507
  • 32
  • 346
  • 385
  • 5
    but if you have string 'test', you got: array([0]=> 0 ) – Dmitry Dubovitsky Oct 09 '13 at 13:39
  • 13
    @Dmitry - that's right.... it's an answer to the OP's question, not a 100% perfect in every case answer to every potential related question. OP had a string of comma-separated numeric values, not a pick-and mix of text and numbers – Mark Baker Oct 09 '13 at 13:46
  • 1
    use array_filter($array, 'is_numeric') better, but It can`not be 100% true, because '0x539', '0b01011' is numeric values. – Dmitry Dubovitsky Oct 09 '13 at 14:07
  • 50
    @Dmitry - if you want to criticise an 18-month old answer to a specific question because it isn't perfect in every conceivable circumstance, and think you have a better solution, then feel free to add your own answer to this question, explaining why your answer is better.... nobody is stopping you... but leave this answer as it is – Mark Baker Oct 09 '13 at 14:10
  • 1
    intval() is **less** performant than **(int)** cast. So better use another solution with (int). see [Method 3 here](http://stackoverflow.com/a/33468638/4840661) – fabpico Apr 19 '16 at 07:24
  • If you're looking for a (slightly) faster solution, check out my answer: http://stackoverflow.com/a/37118395/6191314 – Andreas May 09 '16 at 14:31
  • @mickmackusa This answer is from 2012. Languages evolve, improve, and so answers may change over time. Otherwise, what's the point of bringing new features to a language? I can surely provide more details to my answer, with a link to the documentation for example. But certainly not erase it. My answer shows the difference between the old method and the new way of doing things. There is no one way to do it. – Julien Oct 21 '20 at 08:57
  • I take no issue with your snippet. Your comment has since been deleted since I last commented to you. Your answer is missing its educational explanation and should be edited when you have time. @Julien – mickmackusa Oct 21 '20 at 09:03
  • Better use casting to (int) http://stackoverflow.com/a/37118395/6191314 because PHPStan throws error to this solution: Parameter #1 $callback of function array_map expects (callable(mixed): mixed)|null, 'intval' given. Type array|bool|float|int|resource|string|null of parameter #1 $value of passed callable needs to be same or wider than parameter type mixed of accepting callable. – Ilyich Jun 16 '23 at 16:49
57

So I was curious about the performance of some of the methods mentioned in the answers for large number of integers.

Preparation

Just creating an array of 1 million random integers between 0 and 100. Than, I imploded them to get the string.

  $integers = array();
  
  for ($i = 0; $i < 1000000; $i++) {
      $integers[] = rand(0, 100);
  }

  $long_string = implode(',', $integers);

Method 1

This is the one liner from Mark's answer:

$integerIDs = array_map('intval', explode(',', $long_string));

Method 2

This is the JSON approach:

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

Method 3

I came up with this one as modification of Mark's answer. This is still using explode() function, but instead of calling array_map() I'm using regular foreach loop to do the work to avoid the overhead array_map() might have. I am also parsing with (int) vs intval(), but I tried both, and there is not much difference in terms of performance.

  $result_array = array();
  $strings_array = explode(',', $long_string);
  
  foreach ($strings_array as $each_number) {
      $result_array[] = (int) $each_number;
  }

Results

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

The bottom line is the average. It looks like the first method was a little slower for 1 million integers, but I didn't notice 3x performance gain of Method 2 as stated in the answer. It turned out foreach loop was the quickest one in my case. I've done the benchmarking with Xdebug.

Edit: It's been a while since the answer was originally posted. To clarify, the benchmark was done in php 5.6.40.

Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
MikeWu
  • 3,042
  • 2
  • 19
  • 27
  • 1
    I really do wonder whether the performance stayed the same in PHP 7, and even more curious how would Method 1 array_map combined with method 3 casting and closure/anonymous callback would do... – jave.web Oct 12 '18 at 19:27
  • `array_map(function($v){ return (int)$v; }, $strings_array);` this is what I meant – jave.web Oct 12 '18 at 19:44
  • 1
    I made some tests on PHP7.2 using foreach (method 1), array_map with 'intval' (method 2) and array_map with anonymous function (method 3) in an array with 10000000 elements. I came up with the results that my method 2 is faster (~0.6s), then method 3 (~0.75s), then method 1 (~1.1s) – Gabriel Lima Mar 05 '20 at 14:03
  • various methods provided by the answers in this post do not answer the question that was asked in the title and all 300 thousand people visited this post were misinformed. And yes, such posts pretty much constitute the state of PHP community. – Your Common Sense Jun 02 '22 at 18:51
  • The OP question is `Convert a comma-delimited string into array of integers?`. I guess my understanding of this, is `Convert a string of comma-delimited integers into array of integers` (which seems to be in line with understanding of this question by other responders). You claim the question is `Convert array values from string to int`. Nowhere in the OP post I see, that he starts with an array. I do see `$string = "1,2,3"` on the first line of code, which would imply that the staring point is a string of comma delimited integers. – MikeWu Jun 02 '22 at 19:00
48

This is almost 3 times faster than explode(), array_map() and intval():

$integerIDs = json_decode('[' . $string . ']', true);
aksu
  • 5,221
  • 5
  • 24
  • 39
sgrodzicki
  • 1,064
  • 8
  • 6
  • 1
    @Binod your string has probably a syntax error. It should be formatted like this: $string = "1,2,3"; – sgrodzicki May 07 '13 at 18:00
  • @sgrodzicki.. You are right.. My mistake..+1'd.. It was not commas.. `str_replace` will do that.. I think then also this is faster.. right? – Binod Kalathil May 08 '13 at 06:52
  • Yes, json_decode() + str_replace() will still be faster than explode() + array_map() + intval(). – sgrodzicki May 08 '13 at 11:57
  • 4
    explode() + array_map() + intval() might not be as fast as json_decode() but it is clearly not the better option to choose... you need to handle other stuff like json-syntax errors which are likely when you are sanitizing user input – staabm Mar 28 '14 at 11:11
  • actually, this is *the* answer - if you're sure about the format of the input data, you can safely use this solution as the simplest and fastest way. JSON is usually the way to go - and IMO in many cases it's better to leave verification of data to JSON parser than to handle it manually... –  Apr 26 '14 at 00:35
  • 2
    this is horrible, especially when it's faster than a map + to_int! php, how could it have come that far... – phoet Jun 17 '15 at 07:26
  • This is a Laravel way of doing it. – Yevgeniy Afanasyev Jun 01 '16 at 05:35
  • 3
    This is just micro optimisation. There's no need to optimise such a tiny operation as casting an array filled with strings to integers. And if your array contains lots and lots of elements (e.g. hundreds of thousands of elements), then there's another, much bigger problem in your project than this operation. – Andreas Dec 05 '16 at 10:57
  • 1
    @Andreas doesn't look like micro optimization to me: https://blackfire.io/profiles/compare/6e3fd0ca-261d-47b1-a53f-bc500c87f69b/graph – sgrodzicki Dec 05 '16 at 14:17
  • 2
    Any trick could be valid, especially if it's about performance optimization. Actually this answer also valid if you want to cast to `float` number and not only to `integer`, and you guys didn't realize it. – StefansArya Jan 03 '19 at 01:06
  • 1
    @StefansArya Also `boolean` :-) – AbraCadaver Dec 11 '20 at 17:02
  • "your string has probably a syntax error" - **THAT** is the damn problem. This "method" is but an **ugly hack**, prone to errors of all sorts. All in pursue of imaginary "performance optimization" – Your Common Sense Jun 01 '22 at 07:24
26

Use this code with a closure (introduced in PHP 5.3), it's a bit faster than the accepted answer and for me, the intention to cast it to an integer, is clearer:

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

Output will be:

array(4) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
}
Andreas
  • 2,821
  • 25
  • 30
  • 1
    According to the [doc](http://php.net/manual/en/function.create-function.php), this is also faster than create_function proposed in other answers. – untill Oct 17 '16 at 08:21
  • 1
    @untill Yes, you are right. And create_function is deprecated since PHP 7.2.0. – Andreas Sep 18 '18 at 15:39
19

In Mark's solution, you will return array([0]=> int 0) if you try to parse a string such as "test".

$integerIDs = array_map( 'intval', array_filter( explode(',', $string), 'is_numeric' ) );
Rahul
  • 18,271
  • 7
  • 41
  • 60
Dmitry Dubovitsky
  • 2,186
  • 1
  • 16
  • 24
9

An alternative shorter method could be:

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

It has the same performance as Method 3.

MyGeertRo
  • 129
  • 1
  • 3
7

My solution is casting each value with the help of callback function:

$ids = array_map( function($value) { return (int)$value; }, $ids )
Theva
  • 873
  • 8
  • 15
6

Not sure if this is faster but flipping an array twice will cast numeric strings to integers:

$string = "1,2,3,bla";
$ids = array_flip(array_flip(explode(',', $string)));
var_dump($ids);

Important: Do not use this if you are dealing with duplicate values!

baikho
  • 5,203
  • 4
  • 40
  • 47
  • 1
    This will also damage the data set if the array has duplicate values. There will be real world cases where duplicate values are valid/good/necessary and this answer will cause harm. Because this answer (which stretches the scope of the OP's question) does not cast `bla` as an integer, it is incorrect and I must DV. This answer doesn't satisfy the question title. – mickmackusa Oct 13 '20 at 00:45
  • @mickmackusa I see that is indeed not accounted for. At time of writing in 2016 I found it a neat trick, but I agree it is dangerous. – baikho Oct 13 '20 at 10:52
5

If you have array like:

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

And if you want to covert them into integers and keep within array, following should do the job:

$newArray = array_map( create_function('$value', 'return (int)$value;'),
            $runners);
DPP
  • 12,716
  • 3
  • 49
  • 46
  • 1
    create_function is deprecated since PHP 7.2.0. Better check out my answer without create_function, but with an anonymous function. – Andreas Sep 18 '18 at 15:40
  • 1
    This is an excellent solution, however since `create_function` is deprecated, you can do this instead: `$newArray = array_map(fn($value) => (int) $value, $runners)` – bdereta Mar 18 '22 at 00:22
  • How it's different from the accepted answer? – Your Common Sense Jun 01 '22 at 07:16
5

PHP 7.4 style:

$ids = array_map(fn(string $x): int => (int) $x, explode(',', $string));
Julien
  • 703
  • 1
  • 10
  • 17
  • If you are going to declare the return type, you don't need to explicitly cast as int in the function body. https://3v4l.org/jhWgs – mickmackusa Jan 20 '21 at 00:34
3

Keep it simple...

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

Why are you looking for other ways? Looping does the job without pain. If performance is your concern, you can go with json_decode (). People have posted how to use that, so I am not including it here.

Note: When using == operator instead of === , your string values are automatically converted into numbers (e.g. integer or double) if they form a valid number without quotes. For example:

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

Thus, == may solve your problem, is efficient, but will break if you use === in comparisons.

3

If you have a multi-dimensional array, none of the previously mentioned solutions will work. Here is my solution:

public function arrayValuesToInt(&$array){
  if(is_array($array)){
    foreach($array as &$arrayPiece){
      arrayValuesToInt($arrayPiece);
    }
  }else{
    $array = intval($array);
  }
}

Then, just do this:

arrayValuesToInt($multiDimentionalArray);

This will make an array like this:

[["1","2"]["3","4"]]

look like this:

[[1,2][3,4]]

This will work with any level of depth.

Alternatively, you can use array_walk_recursive() for a shorter answer:

array_walk_recursive($array, function(&$value){
    $value = intval($value);
});
Skeets
  • 4,476
  • 2
  • 41
  • 67
  • This is a deviation from the OP's question. This answer is probably better suited elsewhere -- where recursion is called for. ...and where recursion is called for, php has a native `array` function that `walk`s `recursive`ly through leaf nodes. – mickmackusa Oct 12 '20 at 23:52
  • "This is a deviation from the OP's question" -- well, technically no part of the question header or body ever says that there won't be any multi-dimensional arrays, so anyone looking at this question very well could be looking for a multi-dimensional solution. – Skeets Oct 13 '20 at 03:06
  • Sure, you can use `array_walk_recursive`.... it is a "shorter" solution. Forgot about that one, thanks. (added to answer) – Skeets Oct 13 '20 at 03:06
  • The [mcve] 100% indicates that the input data is a comma-delimited string which is exploded into an indexed 1-dimensional array. You are the only person to contort this question into a recursive task. I have heard the excuse before that some researchers may be looking for "this different answer". To that, I say: "great, we definitely want to share solid techniques, but adhere to "mise en place" (fr. Put in place). The best way to help researchers is to put specific techniques where they are expected to be found. – mickmackusa Oct 13 '20 at 11:08
  • I, again, recommend that you transfer your answer to a more appropriate question or ask the new unique question and answer it. – mickmackusa Oct 13 '20 at 11:08
  • Could you point me to the site policy that says answering with a slightly broader scope that still answers the original question is not allowed? If the OP uses this function going forward, they'll be able to use it with their original problem, and continue to use the function for all arrays, single or multi-dimensional. Quoting you, "this answer DOES add value because it is a unique and working solution".... Is this not a unique and working solution? If you don't agree, go ahead and downvote this answer. – Skeets Oct 14 '20 at 02:08
  • With just under 60 seconds of Googling, I think I found another page where your answer is better suited. https://stackoverflow.com/questions/27147105/php-convert-string-in-array-to-int There may be more places to park your recursive answer, but recursion is overkill for this well-defined task. ... and the inverse: https://stackoverflow.com/q/31599144/2943403 – mickmackusa Oct 14 '20 at 02:24
  • The only thing in the chat was: I disagree, it is in my opinion that my answer is suited for this question. Downvote and move on. I'm done. – Skeets Oct 14 '20 at 02:52
  • I'm not willing to downvote a working, explained, unique answer on a page. – mickmackusa Oct 14 '20 at 02:56
1
$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);

The result will be like this

array(3) {
  [0]=> int(23)
  [1]=> int(25)
  [2]=> int(29)
}
ChungND
  • 131
  • 1
  • 6
0

Input => '["3","6","16","120"]'

Type conversion I used => (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"]'));

Output:

array(4) {
  [0]=>
  int(3)
  [1]=>
  int(6)
  [2]=>
  int(16)
  [3]=>
  int(120)
}

Thanks

Tamil
  • 311
  • 4
  • 9
0
<?php
    
$string = "1,2,3";
$ids = explode(',', $string );

array_walk( $ids, function ( &$id )
{
    $id = (int) $id;
});
var_dump( $ids );
10 Rep
  • 2,217
  • 7
  • 19
  • 33
Al-Amin
  • 596
  • 3
  • 16
0

I'm surprised no one proposed filter_var method, I'm not sure how well it performs on huge datasets, but if your key is validity over performance here is an example:

$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

As you can see 2 3 is not a valid number same as a and were replaced by null

To get rid of empty values you can apply array_filter

$filteredValues = array_filter($filteredValues);

which would produce following result:

array (size=4)
  0 => int 1
  2 => int 4
  3 => int 6
  4 => int 5
Nazariy
  • 6,028
  • 5
  • 37
  • 61
-2

Another technique is to type-hint (coerce) the incoming values to int type after exploding the string.

Note that these techniques will work as demonstrated in my demo link unless you have set php to use strict typing.

The following techniques should not be used to sanitize non-numeric strings; it assumes that all values will be numeric.

If float values are passed into these techniques, they will be truncated/floored to integers.

Code: (Demo)

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

Output:

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)
}
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • I'm not the downvoter -- but all of those solutions will fail in [strict mode](https://www.php.net/manual/en/migration70.new-features.php), so that may be the reason here. It's not the default PHP setting, but it's widely popular. Using `intval()` is going to be the better solution, and that's already the accepted answer, so this answer doesn't add any value. – Skeets Oct 14 '20 at 01:28
  • This answer DOES add value because it is a unique and working solution -- as proven by my demo link. Researchers looking to do benchmarks might entertain these techniques when determining what they wish to use in their own project. I am not claiming that this answer is better or worse than any other answers on this page. I am just providing more working solutions to choose from. – mickmackusa Oct 14 '20 at 01:29