jak przekonwertować wartości tablic z ciągu na int?

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

zwroty

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

Potrzebuję, aby wartości były typu int zamiast ciągu typu. Czy istnieje lepszy sposób na zrobienie tego niż zapętlanie tablicy za pomocą foreach i konwertowanie każdego łańcucha na int?

cwal
źródło

Odpowiedzi:

537

Możesz to osiągnąć, postępując zgodnie z kodem,

$integerIDs = array_map('intval', explode(',', $string));
Mark Baker
źródło
3
ale jeśli masz ciąg „test”, masz: tablicę ([0] => 0)
Dmitry Dubovitsky
10
@Dmitry - zgadza się ... to odpowiedź na pytanie PO, a nie w 100% doskonała w każdym przypadku odpowiedź na każde potencjalne powiązane pytanie. OP miał ciąg wartości liczbowych oddzielonych przecinkami, a nie kombinację tekstu i liczb
Mark Baker,
1
lepiej użyj array_filter ($ array, 'is_numeric'), ale nie może być w 100% prawdą, ponieważ „0x539”, „0b01011” to wartości liczbowe.
Dmitrij Dubowicki
35
@Dmitry - jeśli chcesz skrytykować 18-miesięczną odpowiedź na konkretne pytanie, ponieważ nie jest ona idealna w każdych możliwych okolicznościach i uważasz, że masz lepsze rozwiązanie, możesz dodać własną odpowiedź na to pytanie, wyjaśniając dlaczego twoja odpowiedź jest lepsza .... nikt cię nie powstrzymuje ... ale zostaw tę odpowiedź taką, jaka jest
Mark Baker
intval () jest mniej wydajny niż rzutowanie (int) . Lepiej więc użyj innego rozwiązania z (int). patrz Metoda 3 tutaj
Fabian Picone
43

To jest prawie 3 razy szybciej niż explode(), array_map()i intval():

$integerIDs = json_decode('[' . $string . ']', true);
sgrodzicki
źródło
1
@Binod Twój łańcuch prawdopodobnie ma błąd składniowy. Powinien być sformatowany w następujący sposób: $ string = "1,2,3";
sgrodzicki
4
explode () + array_map () + intval () może nie być tak szybki jak json_decode (), ale najwyraźniej nie jest lepszą opcją do wyboru ... musisz obsługiwać inne rzeczy, takie jak błędy składniowe json, które są prawdopodobne, gdy jesteś dezynfekowanie danych wejściowych użytkownika
staabm
2
to jest okropne, szczególnie gdy jest szybsze niż mapa + to_int! php, jak mogło dojść tak daleko ...
phoet
3
To tylko mikrooptymalizacja. Nie ma potrzeby optymalizacji tak drobnej operacji, jak rzutowanie tablicy wypełnionej ciągami znaków na liczby całkowite. A jeśli twoja tablica zawiera wiele elementów (np. Setki tysięcy elementów), oznacza to, że w twoim projekcie jest o wiele większy problem niż ta operacja.
Andreas,
1
@Andreas nie wygląda mi na mikrooptymalizację: blackfire.io/profiles/compare/…
sgrodzicki
41

Byłem więc ciekawy wydajności niektórych metod wymienionych w odpowiedziach na dużą liczbę liczb całkowitych.

Przygotowanie

Właśnie stworzyłem tablicę 1 miliona losowych liczb całkowitych od 0 do 100. Następnie zaimplodowałem je, aby uzyskać ciąg.

  $integers = array();

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

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

Metoda 1

To jest jedna linijka z odpowiedzi Marka:

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

Metoda 2

Oto podejście JSON:

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

Metoda 3

Wymyśliłem ten jako modyfikację odpowiedzi Marka. To wciąż jest używaneexplode() funkcji, ale zamiast wywoływać array_map(), używam regularnej foreachpętli, aby wykonać pracę, aby uniknąć narzutu array_map(). Parsuję też z (int)vs intval(), ale wypróbowałem oba, i nie ma dużej różnicy pod względem wydajności.

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

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

Wyniki:

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

Dolna linia to średnia. Wygląda na to, że pierwsza metoda była nieco wolniejsza dla 1 miliona liczb całkowitych, ale nie zauważyłem 3-krotnego wzrostu wydajności metody 2, jak stwierdzono w odpowiedzi. Okazało sięforeach pętla była najszybsza w moim przypadku. Przeprowadziłem testy porównawcze z Xdebug.

Edycja: Minęło trochę czasu, odkąd pierwotnie opublikowano odpowiedź. Aby to wyjaśnić, test został przeprowadzony w php 5.6.

MikeWu
źródło
1
Naprawdę zastanawiam się, czy wydajność pozostała niezmieniona w PHP 7, a jeszcze bardziej ciekawe, jak miałaby metoda metoda array_map w połączeniu z rzutowaniem metody 3 i zamykaniem / anonimowym wywołaniem zwrotnym ...
jave.web
array_map(function($v){ return (int)$v; }, $strings_array);o to mi chodziło
jave.web
Zrobiłem kilka testów na PHP7.2 przy użyciu foreach (metoda 1), array_map z 'intval' (metoda 2) i array_map z anonimową funkcją (metoda 3) w tablicy z 10000000 elementów. Doszedłem do wniosku, że moja metoda 2 jest szybsza (~ 0,6 s), następnie metoda 3 (~ 0,75 s), a następnie metoda 1 (~ 1,1 s)
Gabriel Lima
20

Użyj tego kodu z zamknięciem (wprowadzonym w PHP 5.3), jest to nieco szybsze niż zaakceptowana odpowiedź, a dla mnie zamiar przekazania go na liczbę całkowitą jest wyraźniejszy:

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

Dane wyjściowe będą:

array(4) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
}
Andreas
źródło
1
Według doktora jest to również szybsze niż funkcja create_funkcji zaproponowana w innych odpowiedziach.
do
1
@untill Tak, masz rację. A funkcja create_function jest przestarzała od PHP 7.2.0.
Andreas
14

W rozwiązaniu Marka wrócisz, array([0]=> int 0)jeśli spróbujesz parsować ciąg taki jak „test”.

$integerIDs = array_map( 'intval', array_filter( explode(',', $string), 'is_numeric' ) );
Dmitrij Dubowicki
źródło
7

Nie jestem pewien, czy jest to szybsze, ale dwukrotne odwrócenie tablicy spowoduje rzut ciągów liczbowych na liczby całkowite:

$string = "1,2,3, bla";
$ids = array_flip(array_flip(explode(',', $string)));
var_dump($ids);
baikho
źródło
7

Alternatywną krótszą metodą może być:

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

Ma taką samą wydajność jak metoda 3.

MyGeertRo
źródło
najkrótsze, ale elastyczne rozwiązanie dla mnie.
Ryan Arief,
5

Jeśli masz tablicę typu:

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

A jeśli chcesz ukryć je w liczbach całkowitych i zachować w obrębie tablicy, wykonaj następujące czynności:

$newArray = array_map( create_function('$value', 'return (int)$value;'),
            $runners);
star18bit
źródło
Funkcja create_function jest przestarzała od PHP 7.2.0. Lepiej sprawdź moją odpowiedź bez funkcji create_function, ale z anonimową funkcją.
Andreas
4

Moje rozwiązanie rzuca każdą wartość za pomocą funkcji zwrotnej:

$ids = array_map( function($value) { return (int)$value; }, $ids )
Theva
źródło
3

Nie komplikuj...

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

Dlaczego szukasz innych sposobów? Pętla wykonuje pracę bez bólu. Jeśli zależy Ci na wydajności, możesz iść dalej json_decode (). Ludzie napisali, jak z tego korzystać, więc nie zamieszczam go tutaj.

Uwaga: W przypadku użycia operatora == zamiast === wartości ciągu są automatycznie konwertowane na liczby (np. Liczba całkowita lub podwójna), jeśli tworzą poprawną liczbę bez cudzysłowów. Na przykład:

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

Tak więc == może rozwiązać twój problem, jest wydajny, ale zepsuje się, jeśli użyjesz === w porównaniach.

Devashish Jaiswal
źródło
2

Jeśli masz tablicę wielowymiarową, żadne z wcześniej wymienionych rozwiązań nie będzie działać. Oto moje rozwiązanie:

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

Następnie zrób to:

arrayValuesToInt($multiDimentionalArray);

Spowoduje to utworzenie takiej tablicy:

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

wygląda jak to:

[[1,2][3,4]

(Będzie to działać na dowolnym poziomie głębokości)

Skeets
źródło
1

Możesz przekonwertować wartości w tablicy:

<?php

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

Możesz także zwrócić wartość zwracaną przez explodefunkcję do$strings i iterować ją zamiast używać innej zmiennej ($ ids).

Myślę, że to rozwiązanie jest najbezpieczniejszym sposobem z najlepszą wydajnością.

Roham Rafii
źródło
1

Styl PHP 7.4:

$ids = array_map(fn(string $x): int => (int) $x, explode(',', $string));
Julien
źródło
0

Wejście => „[„ 3 ”,„ 6 ”,„ 16 ”,„ 120 ”]”

Konwersja typu, którego użyłem => (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"]'));

Wynik:

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

Dzięki

Manoj Kumar
źródło