comment convertir des valeurs de tableau de chaîne en int?


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

Retour

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

J'ai besoin que les valeurs soient de type int au lieu de type chaîne. Existe-t-il une meilleure façon de le faire que de parcourir le tableau avec un foreach et de convertir chaque chaîne en int?

Réponses:


537

Vous pouvez y parvenir en suivant le code,

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

3
mais si vous avez la chaîne 'test', vous obtenez: array ([0] => 0)
Dmitry Dubovitsky

10
@Dmitry - c'est vrai .... c'est une réponse à la question du PO, pas une réponse à 100% parfaite dans chaque cas à chaque question connexe potentielle. OP avait une chaîne de valeurs numériques séparées par des virgules, pas une sélection et un mélange de texte et de nombres
Mark Baker

1
utilisez mieux array_filter ($ array, 'is_numeric'), mais cela ne peut pas être vrai à 100%, car '0x539', '0b01011' sont des valeurs numériques.
Dmitry Dubovitsky

35
@Dmitry - si vous voulez critiquer une réponse vieille de 18 mois à une question spécifique parce qu'elle n'est pas parfaite dans toutes les circonstances imaginables, et pensez que vous avez une meilleure solution, alors n'hésitez pas à ajouter votre propre réponse à cette question, en expliquant pourquoi votre réponse est meilleure .... personne ne vous arrête ... mais laissez cette réponse telle quelle
Mark Baker

intval () est moins performant que (int) cast. Il vaut donc mieux utiliser une autre solution avec (int). voir la méthode 3 ici
Fabian Picone

43

Ceci est presque 3 fois plus rapide que explode(), array_map()et intval():

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

1
@Binod, votre chaîne contient probablement une erreur de syntaxe. Il doit être formaté comme ceci: $ string = "1,2,3";
sgrodzicki

4
explode () + array_map () + intval () n'est peut-être pas aussi rapide que json_decode () mais ce n'est clairement pas la meilleure option à choisir ... vous devez gérer d'autres choses comme des erreurs de syntaxe json qui sont probables lorsque vous êtes désinfection de l'utilisateur
staabm

2
c'est horrible, surtout quand c'est plus rapide qu'une carte + to_int! php, comment cela a-t-il pu arriver si loin ...
phoet

3
Ce n'est qu'une micro-optimisation. Il n'est pas nécessaire d'optimiser une opération aussi minuscule que la conversion d'un tableau rempli de chaînes en entiers. Et si votre tableau contient beaucoup, beaucoup d'éléments (par exemple des centaines de milliers d'éléments), alors il y a un autre problème, beaucoup plus important dans votre projet que cette opération.
Andreas

1
@Andreas ne ressemble pas à la micro-optimisation pour moi: blackfire.io/profiles/compare/…
sgrodzicki

41

J'étais donc curieux de connaître les performances de certaines des méthodes mentionnées dans les réponses pour un grand nombre d'entiers.

Préparation

Je viens de créer un tableau de 1 million d'entiers aléatoires entre 0 et 100. Ensuite, je les ai implosés pour obtenir la chaîne.

  $integers = array();

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

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

Méthode 1

C'est le seul revêtement de la réponse de Mark:

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

Méthode 2

Voici l'approche JSON:

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

Méthode 3

J'ai proposé celui-ci comme modification de la réponse de Mark. Cela utilise toujours la explode()fonction, mais au lieu d'appeler, array_map()j'utilise une foreachboucle régulière pour faire le travail afin d'éviter la surcharge array_map(). Je suis également en train d'analyser avec (int)vs intval(), mais j'ai essayé les deux, et il n'y a pas beaucoup de différence en termes de performances.

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

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

Résultats:

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

L'essentiel est la moyenne. Il semble que la première méthode ait été un peu plus lente pour 1 million d'entiers, mais je n'ai pas remarqué un gain de performances 3 fois supérieur à la méthode 2, comme indiqué dans la réponse. Il s'est avéré que la foreachboucle était la plus rapide dans mon cas. J'ai fait l'analyse comparative avec Xdebug.

Edit: Cela fait un moment que la réponse n'a pas été publiée à l'origine. Pour clarifier, le benchmark a été fait en php 5.6.


1
Je me demande vraiment si les performances sont restées les mêmes en PHP 7, et encore plus curieux de voir comment la méthode 1 array_map combinée à la conversion et à la fermeture / rappel anonyme de la méthode 3 feraient ...
jave.web

array_map(function($v){ return (int)$v; }, $strings_array);c'est ce que je voulais dire
jave.web

J'ai fait quelques tests sur PHP7.2 en utilisant foreach (méthode 1), array_map avec 'intval' (méthode 2) et array_map avec fonction anonyme (méthode 3) dans un tableau avec 10000000 éléments. Je suis arrivé avec les résultats que ma méthode 2 est plus rapide (~ 0,6 s), puis la méthode 3 (~ 0,75 s), puis la méthode 1 (~ 1,1 s)
Gabriel Lima

20

Utilisez ce code avec une fermeture (introduit dans PHP 5.3), c'est un peu plus rapide que la réponse acceptée et pour moi, l'intention de le convertir en un entier, est plus claire:

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

La sortie sera:

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

1
Selon le doc , c'est aussi plus rapide que create_function proposé dans d'autres réponses.
jusqu'au

1
@ jusqu'à ce que vous ayez raison. Et create_function est obsolète depuis PHP 7.2.0.
Andreas

14

Dans la solution de Mark, vous reviendrez array([0]=> int 0)si vous essayez d'analyser une chaîne telle que "test".

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

7

Je ne sais pas si cela est plus rapide, mais retourner le tableau deux fois convertira des chaînes numériques en entiers:

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

7

Une autre méthode plus courte pourrait être:

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

Il a les mêmes performances que la méthode 3.


la solution la plus courte mais flexible pour moi.
Ryan Arief

5

Si vous avez un tableau comme:

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

Et si vous souhaitez les convertir en nombres entiers et les conserver dans le tableau, ce qui suit devrait faire l'affaire:

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

create_function est obsolète depuis PHP 7.2.0. Mieux vaut vérifier ma réponse sans create_function, mais avec une fonction anonyme.
Andreas

4

Ma solution consiste à convertir chaque valeur à l'aide de la fonction de rappel:

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

3

Rester simple...

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

Pourquoi cherchez-vous d'autres moyens? La boucle fait le travail sans douleur. Si la performance est votre préoccupation, vous pouvez y aller json_decode (). Les gens ont posté comment l'utiliser, donc je ne l'inclus pas ici.

Remarque: Lorsque vous utilisez l'opérateur == au lieu de ===, vos valeurs de chaîne sont automatiquement converties en nombres (par exemple entier ou double) si elles forment un nombre valide sans guillemets. Par exemple:

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

Ainsi, == peut résoudre votre problème, est efficace, mais se cassera si vous utilisez === dans les comparaisons.


2

Si vous disposez d'un réseau multidimensionnel, aucune des solutions mentionnées précédemment ne fonctionnera. Voici ma solution:

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

Ensuite, faites ceci:

arrayValuesToInt($multiDimentionalArray);

Cela fera un tableau comme celui-ci:

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

ressemble à ca:

[[1,2][3,4]

(Cela fonctionnera avec n'importe quel niveau de profondeur)


1

Vous pouvez convertir des valeurs dans le tableau:

<?php

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

Vous pouvez également renvoyer la valeur de retour de la explodefonction $stringset l'itérer au lieu d'utiliser une autre variable ($ ids).

Je pense que cette solution est le moyen le plus sûr avec les meilleures performances.


1

Style PHP 7.4:

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

0

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

Conversion de type que j'ai utilisée => (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"]'));

Production:

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

Merci

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.