como converter valores de matriz de string para int?

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

retorna

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

Eu preciso que os valores sejam do tipo int em vez do tipo string. Existe uma maneira melhor de fazer isso do que fazer um loop pela matriz com um foreach e converter cada string em int?

cwal
fonte

Respostas:

537

Você pode conseguir isso seguindo o código,

$integerIDs = array_map('intval', explode(',', $string));
Mark Baker
fonte
3
mas se você tiver a string 'test', terá: array ([0] => 0)
Dmitry Dubovitsky
10
@ Dmitry - isso mesmo ... é uma resposta para a pergunta do OP, não uma resposta 100% perfeita em todos os casos para todas as possíveis questões relacionadas. OP teve uma série de valores numéricos separados por vírgulas, e não uma pick-e mistura de números e de texto
Mark Baker
1
use array_filter ($ array, 'is_numeric') melhor, mas não pode ser 100% verdadeiro, porque '0x539', '0b01011' são valores numéricos.
Dmitry Dubovitsky
35
@Dmitry - se você deseja criticar uma resposta de 18 meses para uma pergunta específica, porque ela não é perfeita em todas as circunstâncias possíveis e acha que tem uma solução melhor, sinta-se à vontade para adicionar sua própria resposta a essa pergunta, explicando por isso que a sua resposta é melhor .... ninguém está parando ... mas deixar esta resposta como é
Mark Baker
intval () tem menos desempenho que (int) cast. Então, é melhor usar outra solução com (int). veja Método 3 aqui
Fabian Picone
43

Isso é quase 3 vezes mais rápido do que explode(), array_map()e intval():

$integerIDs = json_decode('[' . $string . ']', true);
sgrodzicki
fonte
1
@Binod sua string provavelmente tem um erro de sintaxe. Deve ser formatado assim: $ string = "1,2,3";
Sgrodzicki
4
explode () + array_map () + intval () pode não ser tão rápido quanto json_decode (), mas claramente não é a melhor opção para escolher ... você precisa lidar com outras coisas, como erros de sintaxe json, que provavelmente ocorrem quando você está higienizando a entrada do usuário
staabm 28/03
2
isso é horrível, especialmente quando é mais rápido que um mapa + para_int! php, como poderia ter chegado tão longe ...
phoet
3
Isso é apenas micro otimização. Não há necessidade de otimizar uma operação tão pequena como converter uma matriz cheia de strings para números inteiros. E se o seu array contiver muitos e muitos elementos (por exemplo, centenas de milhares de elementos), haverá outro problema muito maior no seu projeto do que esta operação.
Andreas
1
Não @Andreas se parece com micro otimização para mim: blackfire.io/profiles/compare/...
sgrodzicki
41

Então, fiquei curioso sobre o desempenho de alguns dos métodos mencionados nas respostas para um grande número de números inteiros.

Preparação

Apenas criando uma matriz de 1 milhão de números inteiros aleatórios entre 0 e 100. Então, eu os implodi para obter a sequência.

  $integers = array();

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

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

Método 1

Este é o argumento da resposta de Mark:

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

Método 2

Esta é a abordagem JSON:

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

Método 3

Eu vim com este aqui como modificação da resposta de Mark. Isso ainda está usando a explode()função, mas, em vez de chamar array_map(), estou usando um foreachloop regular para fazer o trabalho para evitar a sobrecarga array_map(). Também estou analisando com (int)vs intval(), mas tentei ambos, e não há muita diferença em termos de desempenho.

  $result_array = array();
  $strings_array = explode(',', $long_string);

  foreach ($strings_array as $each_number) {
      $result_array[] = (int) $each_number;
  }

Resultados:

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

A linha inferior é a média. Parece que o primeiro método foi um pouco mais lento para 1 milhão de números inteiros, mas não notei um ganho de desempenho 3x do Método 2, conforme indicado na resposta. Acabou que o foreachloop foi o mais rápido no meu caso. Eu fiz o benchmarking com o Xdebug.

Editar: Já faz um tempo desde que a resposta foi postada originalmente. Para esclarecer, o benchmark foi realizado no php 5.6.

MikeWu
fonte
1
Eu realmente me pergunto se o desempenho permaneceu o mesmo em PHP 7, e ainda mais curioso como seria Método 1 array_map combinado com o método 3 fundição e fechamento / retorno de chamada anônima faria ...
jave.web
array_map(function($v){ return (int)$v; }, $strings_array);isto é o que eu quis dizer
jave.web
Fiz alguns testes no PHP7.2 usando foreach (método 1), array_map com 'intval' (método 2) e array_map com função anônima (método 3) em uma matriz com 10000000 elementos. Eu vim com os resultados de que meu método 2 é mais rápido (~ 0,6s), depois método 3 (~ 0,75s) e depois método 1 (~ 1,1s)
Gabriel Lima
20

Use esse código com um fechamento (introduzido em PHP 5.3), é um pouco mais rápido que a resposta aceita e, para mim, a intenção de convertê-lo em um número inteiro é mais clara:

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

A saída será:

array(4) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
}
Andreas
fonte
1
De acordo com o documento , isso também é mais rápido do que a função create_ proposta em outras respostas.
até
1
@untill Sim, você está certo. E create_function está obsoleto desde o PHP 7.2.0.
Andreas
14

Na solução de Mark, você retornará array([0]=> int 0)se tentar analisar uma string como "test".

$integerIDs = array_map( 'intval', array_filter( explode(',', $string), 'is_numeric' ) );
Dmitry Dubovitsky
fonte
7

Não tenho certeza se isso é mais rápido, mas inverter a matriz duas vezes converterá seqüências numéricas em números inteiros:

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

Um método alternativo mais curto pode ser:

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

Tem o mesmo desempenho que o método 3.

MyGeertRo
fonte
a solução mais curta e flexível para mim.
perfil completo de Ryan Arief
5

Se você tiver uma matriz como:

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

E se você deseja disfarçá-los em números inteiros e manter-se dentro da matriz, faça o seguinte:

$newArray = array_map( create_function('$value', 'return (int)$value;'),
            $runners);
star18bit
fonte
A função create_function está obsoleta desde o PHP 7.2.0. Melhor verificar minha resposta sem create_function, mas com uma função anônima.
Andreas
4

Minha solução está lançando cada valor com a ajuda da função de retorno de chamada:

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

Mantenha simples...

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

Por que você está procurando outras maneiras? Looping faz o trabalho sem dor. Se o desempenho é sua preocupação, você pode prosseguir json_decode (). As pessoas postaram como usar isso, então não estou incluindo aqui.

Nota: Ao usar o operador == em vez de ===, seus valores de sequência são convertidos automaticamente em números (por exemplo, número inteiro ou duplo) se formarem um número válido sem aspas. Por exemplo:

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

Portanto, == pode resolver seu problema, é eficiente, mas será interrompido se você usar === nas comparações.

Devashish Jaiswal
fonte
2

Se você tiver uma matriz multidimensional, nenhuma das soluções mencionadas anteriormente funcionará. Aqui está a minha solução:

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

Então, faça o seguinte:

arrayValuesToInt($multiDimentionalArray);

Isso criará uma matriz como esta:

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

parece com isso:

[[1,2][3,4]

(Isso funcionará com qualquer nível de profundidade)

Skeets
fonte
1

Você pode converter valores na matriz:

<?php

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

Você também pode retornar o valor de retorno da explodefunção $stringse iterá-lo em vez de usar outra variável ($ ids).

Eu acho que essa solução é a maneira mais segura e com o melhor desempenho.

Roham Rafii
fonte
1

Estilo PHP 7.4:

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

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

Conversão de tipo que usei => (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"]'));

Resultado:

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

obrigado

Manoj kumar
fonte