将逗号分隔的字符串转换为整数数组?

以下代码:

$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遍历数组并将每个string转换为int更好的方法呢?

326996 次浏览

你可以通过以下代码来实现这一点,

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

这几乎比explode()array_map()intval()快3倍:

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

在Mark的解决方案中,如果你试图解析“test”这样的字符串,你将返回array([0]=> int 0)

$integerIDs = array_map( 'intval', array_filter( explode(',', $string), 'is_numeric' ) );

所以我很好奇答案中提到的一些方法对于大量整数的性能。

准备

只是创建一个100万个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()函数,但我使用常规的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

底线是平均值。对于100万个整数,第一种方法看起来有点慢,但我没有注意到答案中所述的方法2的性能提高了3倍。在我的例子中,foreach循环是最快的。我已经用Xdebug完成了基准测试。

编辑:从最初的答案发布到现在已经有一段时间了。为了澄清,基准测试是在php 5.6.40中完成的。

保持简单……

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

你为什么要另辟蹊径?循环毫无痛苦地完成了这项工作。如果你关心的是性能,你可以使用json_decode ()。人们已经发布了如何使用它,所以我在这里不包括它。

注意:当使用==操作符而不是===时,如果字符串值构成了一个不带引号的有效数字,则会自动转换为数字(例如整数或双精度)。例如:

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

因此,==可以解决你的问题,是有效的,但如果你在比较中使用===就会崩溃。

如果你有这样的数组:

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

如果你想把它们转换成整数并保持在数组中,下面应该做的工作:

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

使用此代码与闭包(在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)
}

不确定这是否更快,但翻转数组两次会将数值字符串转换为整数:

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

重要的是:如果你正在处理重复的值,不要使用这个!

如果您有一个多维数组,前面提到的解决方案都不起作用。以下是我的解决方案:

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]]

这适用于任何深度。

或者,你可以使用array_walk_recursive()来得到一个更简短的答案:

array_walk_recursive($array, function(&$value){
$value = intval($value);
});

另一种更短的方法是:

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

其性能与方法3相同。

我的解决方案是在回调函数的帮助下转换每个值:

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

PHP 7.4风格:

$ids = array_map(fn(string $x): int => (int) $x, explode(',', $string));

__abc0 => '["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)
}

谢谢

<?php
    

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


array_walk( $ids, function ( &$id )
{
$id = (int) $id;
});
var_dump( $ids );

另一种技术是在字符串爆炸后,将传入值type-hint(强制)为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)
}
$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)
}

我很惊讶没有人提出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