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

313
以下代码:
$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


1
对于寻找适用于多维数据的解决方案的研究人员,请参阅此类似问题:https://stackoverflow.com/questions/27147105/php-convert-string-in-array-to-int - mickmackusa
18个回答

723

你可以通过以下代码实现此功能,

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

5
但如果您有字符串“test”,则会得到:array([0] => 0) - Dmitry Dubovitsky
13
@Dmitry - 没错... 这是对 OP 的问题的回答,而不是对每个潜在相关问题的 100% 完美答案。OP 有一串逗号分隔的数字值,而不是文本和数字的混合选择。 - Mark Baker
1
使用array_filter($array, 'is_numeric')更好,但它并不是100%准确的,因为'0x539'、'0b01011'是数值。 - Dmitry Dubovitsky
50
@Dmitry - 如果你想批评一个18个月前的回答,因为它在所有可能情况下都不完美,并且认为你有更好的解决方案,请随时在这个问题下添加你自己的答案,解释为什么你的答案更好...没有人会阻止你...但请不要改变这个回答。 - Mark Baker
1
intval()的性能比(int)转换差。因此最好使用另一种带有(int)的解决方案。请参见此处的方法3 - fabpico
显示剩余4条评论

57

我对回答中提到的处理大量整数方法的性能感到好奇。

准备工作

只需创建一个包含 0 到 100 之间的 1 百万个随机整数的数组。然后,将它们压缩成字符串。

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

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

方法1

这是Mark答案中的一行代码:

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

方法二

这是JSON的方法:

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

方法三

我将这个方法作为 Mark 答案的修改版提出。仍然使用 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倍的性能提升。结果证明,在我的情况下,foreach循环是最快的。我使用了Xdebug进行基准测试。

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


1
我真的很想知道在PHP 7中性能是否保持不变,更加好奇的是Method 1 array_map与method 3 casting和closure/anonymous callback结合起来会怎样表现... - jave.web
array_map(function($v){ return (int)$v; }, $strings_array); 这就是我的意思。 - jave.web
1
我对PHP7.2进行了一些测试,使用foreach(方法1),array_map与'intval'(方法2)以及在一个包含10000000个元素的数组中使用匿名函数的array_map(方法3)。 我的测试结果表明,方法2更快(约0.6秒),然后是方法3(约0.75秒),最后是方法1(约1.1秒)。 - Gabriel Lima
这篇帖子中提供的各种方法并没有回答标题中所问的问题,所有30万访问者都被误导了。是的,这样的帖子基本上构成了PHP社区的现状。 - Your Common Sense
OP的问题是“将逗号分隔的字符串转换为整数数组?”。 我猜我的理解是“将逗号分隔的整数字符串转换为整数数组”(这似乎符合其他回答者对此问题的理解)。 你声称问题是“将字符串中的数组值转换为int”。我在OP帖子中没有看到他从数组开始的地方。我确实看到第一行代码中的$string =“1,2,3”,这意味着起始点是一个逗号分隔的整数字符串。 - MikeWu

48

这比explode()array_map()intval()快近3倍:

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

1
@Binod,你的字符串可能有语法错误。它应该格式化为:$string = "1,2,3"; - sgrodzicki
4
explode() + array_map() + intval() 可能不如 json_decode() 快,但显然不是更好的选择... 当您正在清理用户输入时,需要处理其他内容,例如可能发生的 JSON 语法错误。 - staabm
2
这太可怕了,特别是当它比 map + to_int 还快的时候!PHP,它怎么会走到这一步呢... - phoet
3
这只是微小的优化,没有必要优化将填充有字符串的数组转换为整数的这种微小操作。如果你的数组包含大量元素(例如数十万个元素),那么你项目中存在比这个操作更严重得多的问题。 - Andreas
2
任何技巧都可能是有效的,特别是当涉及到性能优化时。实际上,如果你想将数字转换为float类型而不仅仅是整数,这个答案也是有效的,而你们可能没有意识到这一点。 - StefansArya
显示剩余7条评论

26

使用闭包(在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更快。 - untill
1
@untill 是的,你说得对。而且自 PHP 7.2.0 起,create_function 已被弃用。 - Andreas

19

在Mark的解决方案中,如果您尝试解析像"test"这样的字符串,您将返回array([0]=> int 0)

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

9
一个更短的替代方法可能是:
$r = explode(',', $s);
foreach ($r as &$i) $i = (int) $i;

它的表现与方法3相同。


7

我的解决方案是利用回调函数将每个值强制转换:

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

$ids = \array_map(fn(string $id): int => (int) $id, $ids); - 在 PHP 7.4+ 中更加优美。 - Elliot Reed

6

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

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

重要提示:如果您处理的是重复值,请勿使用此选项!


1
如果数组中有重复的值,这也会损坏数据集。在现实世界中,有些情况下重复的值是有效/好的/必要的,而这个答案会造成伤害。因为这个答案(扩大了OP问题的范围)没有将bla转换为整数,所以它是不正确的,我必须DV。这个答案不能满足问题标题。 - mickmackusa
@mickmackusa 我看到确实没有考虑到这一点。在2016年写作时,我觉得这是一个不错的技巧,但我同意它是危险的。 - baikho

5
如果你有以下这样的一个数组:
$runners = ["1","2","3","4"];

如果您想将它们转换为整数并保留在数组中,可以使用以下方法:

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

1
create_function自PHP 7.2.0起已被弃用。最好查看我的答案,使用匿名函数而不是create_function。 - Andreas
1
这是一个很好的解决方案,但由于create_function已被弃用,您可以改为使用以下代码:$newArray = array_map(fn($value) => (int) $value, $runners) - bdereta
它与被接受的答案有何不同? - Your Common Sense

5

PHP 7.4 风格:

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

如果您要声明返回类型,则不需要在函数体中显式转换为int。 https://3v4l.org/jhWgs - mickmackusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接