Converting comma-separated string of single-quoted numbers to int array - php

I have a string:
'24','27','38'
I want to convert it:
(
[0] => 24
[1] => 27
[2] => 38
)
The conversion: https://3v4l.org/oDPDl
array_map('intval', explode(',', $string))
gives:
Array
(
[0] => 0
[1] => 0
[2] => 0
)
Basically, array_map() works when the numbers aren't quoted like `24,27,38', but I need a technique that works with quoted numbers.
One solution is looping over the array, but I don't want to do that. Can I achieve the above using only php functions (not control structures -- e.g. foreach())?

Use the following approach:
$str = "'24','27','38'";
$result = array_map(function($v){ return (int) trim($v, "'"); }, explode(",", $str));
var_dump($result);
The output:
array(3) {
[0]=>
int(24)
[1]=>
int(27)
[2]=>
int(38)
}

$arr = explode (",", str_replace("'", "", $str));
foreach ($arr as $elem)
$array[] = trim($elem) ;

sscanf() can instantly return type-cast values if you ask it to.
Here is a technique that doesn't use an explicit loop: sscanf(preg_replace())
Code: (Demo)
var_export(sscanf($string, preg_replace('/\d+/', '%d', $string)));
Output:
array (
0 => 24,
1 => 27,
2 => 38,
)
Or some developers might find this more professional/intuitive (other will disagree): (Demo)
var_export(filter_var_array(explode("','", trim($string, "'")), FILTER_VALIDATE_INT));
// same output as above
or perhaps this alternative which leverages more commonly used native functions:
var_export(
array_map(
function($v) {
return (int)$v;
},
explode("','", trim($string, "'"))
)
);
which simplifies to:
var_export(array_map('intval', explode("','", trim($string, "'"))));
// same output as above
For anyone who doesn't care about the datatype of the newly generated elements in the output array, here are a few working techniques that return string elements: (Demo)
var_export(explode("','", trim($string, "'")));
var_export(preg_split('/\D+/', $string, -1, PREG_SPLIT_NO_EMPTY));
var_export(preg_match_all('/\d+/', $string, $m) ? $m[0] : []);
var_export(filter_var_array(explode(',', $string), FILTER_SANITIZE_NUMBER_INT));

Without looping:
$str= "'24','27','38'";
$arr = array_map("intval", explode(",", str_replace("'", "", $str)));
var_dump($arr);
Output:
array(3) {
[0]=>
int(24)
[1]=>
int(27)
[2]=>
int(38)
}

Related

Separate items in a string into two arrays

How can I split this string into two arrays in PHP? The string may have many items in it.
$str = "20x9999,24x65,40x5";
I need to get two arrays from this string:
$array1 = array(20,24,40);
$array2 = array(9999,65,5);
I've tried many implementations of preg_split, slice, regex. I can't get it done... I need help!
You can explode the string by commas, and then explode each of those values by x, inserting the result values from that into the two arrays:
$str = "20x9999,24x65,40x5";
$array1 = array();
$array2 = array();
foreach (explode(',', $str) as $xy) {
list($x, $y) = explode('x', $xy);
$array1[] = $x;
$array2[] = $y;
}
Alternatively, you can use preg_match_all, matching against the digits either side of the x:
preg_match_all('/(\d+)x(\d+)/', $str, $matches);
$array1 = $matches[1];
$array2 = $matches[2];
In both cases the output is:
Array
(
[0] => 20
[1] => 24
[2] => 40
)
Array
(
[0] => 9999
[1] => 65
[2] => 5
)
Demo on 3v4l.org
I guess with preg_split, we could do so:
$str = '20x9999,24x65,40x5';
$array1 = $array2 = array();
foreach (preg_split("/,/", $str, -1, PREG_SPLIT_NO_EMPTY) as $key => $value) {
$val = preg_split("/x/", $value, -1, PREG_SPLIT_NO_EMPTY);
array_push($array1, $val[0]);
array_push($array2, $val[1]);
}
var_dump($array1);
var_dump($array2);
Output
array(3) {
[0]=>
string(2) "20"
[1]=>
string(2) "24"
[2]=>
string(2) "40"
}
array(3) {
[0]=>
string(4) "9999"
[1]=>
string(2) "65"
[2]=>
string(1) "5"
}

php - function to sort an array alphabetically with uppercase letters first

I'm trying to sort an array alphabetically with uppercase letters first in the array
Example:
array(7) {
["H"]=>
int(1)
["W"]=>
int(1)
["e"]=>
int(1)
["l"]=>
int(3)
["o"]=>
int(2)
["r"]=>
int(1)
["d"]=>
int(1)
}
My code doesn't sort with uppercase letters, only alphabetically
Here is my code:
function count_char($str) {
$chars = str_split($str);
$char_counter = Array();
foreach($chars as $char)
if ((ord($char) >= 65 && ord($char) <= 90) ||
(ord($char) >= 97 && ord($char) <= 122)) {
if(!isset($char_counter[$char])) $char_counter[$char] = 1;
else $char_counter[$char] += 1;
}
return $char_counter;
}
var_dump(count_char("Hello World"));
My desired output is $str, I would like alphabetizing the uppers, then alphabetizing the lowers
Personally I would do it like:
<?php
$str = "Hello World";
// split the string (ignoring spaces)
$array = str_split(str_replace(' ', '', $str), 1);
// count the chars
$array = array_count_values($array);
// sort naturally
array_multisort(array_keys($array), SORT_NATURAL, $array);
print_r($array);
https://3v4l.org/aZqRb
Result:
Array
(
[H] => 1
[W] => 1
[d] => 1
[e] => 1
[l] => 3
[o] => 2
[r] => 1
)
Edit: If you want to sort by value and then by key:
<?php
$str = "Hello World";
// split the string (ignoring spaces)
$array = str_split(str_replace(' ', '', $str), 1);
// count the chars
$array = array_count_values($array);
// get the keys
$keys = array_keys($array);
// sort my keys
array_multisort($array, $keys);
// combine sorted keys with array
$array = array_combine($keys, $array);
print_r($array);
https://3v4l.org/pfEin
Result:
Array
(
[H] => 1
[W] => 1
[d] => 1
[e] => 1
[r] => 1
[o] => 2
[l] => 3
)
ksort() will do. You should only call ord() once and just store the result to minimize function calls. ...or better just call ctype_alpha() to ensure you are only storing letters. I recommend adding curly brackets for improved readability.
Code: (Demo)
function count_char($str) {
$chars = str_split($str);
$char_counter = array();
foreach($chars as $char) {
if (ctype_alpha($char)) {
if (!isset($char_counter[$char])) {
$char_counter[$char] = 1;
} else {
++$char_counter[$char];
}
}
}
ksort($char_counter);
return $char_counter;
}
var_dump(count_char("Hello World"));
Output:
array(7) {
["H"]=>
int(1)
["W"]=>
int(1)
["d"]=>
int(1)
["e"]=>
int(1)
["l"]=>
int(3)
["o"]=>
int(2)
["r"]=>
int(1)
}
You could also condense things like this if you aren't scared off by regex:
function count_char($str) {
$letters = preg_split('~[^a-z]*~i', $str, -1, PREG_SPLIT_NO_EMPTY);
if (!$letters) return [];
$counts = array_count_values($letters);
ksort($counters);
return $counters;
}
var_dump(count_char("Hello World"));

Explode comma separated integers to intvals? [duplicate]

This question already has answers here:
Convert a comma-delimited string into array of integers?
(17 answers)
Closed 9 years ago.
Say I have a string like so $thestring = "1,2,3,8,2".
If I explode(',', $thestring) it, I get an array of strings. How do I explode it to an array of integers instead?
array_map also could be used:
$s = "1,2,3,8,2";
$ints = array_map('intval', explode(',', $s ));
var_dump( $ints );
Output:
array(5) {
[0]=> int(1)
[1]=> int(2)
[2]=> int(3)
[3]=> int(8)
[4]=> int(2)
}
Example codepad.
Use something like this:
$data = explode( ',', $thestring );
array_walk( $data, 'intval' );
http://php.net/manual/en/function.array-walk.php
For the most part you shouldn't really need to (PHP is generally good with handling casting strings and floats/ints), but if it is absolutely necessary, you can array_walk with intval or floatval:
$arr = explode(',','1,2,3');
// use floatval if you think you are going to have decimals
array_walk($arr,'intval');
print_r($arr);
Array
(
[0] => 1
[1] => 2
[2] => 3
)
If you need something a bit more verbose, you can also look into settype:
$arr = explode(",","1,2,3");
function fn(&$a){settype($a,"int");}
array_walk($f,"fn");
print_r($f);
Array
(
[0] => 1
[1] => 2
[2] => 3
)
That could be particularly useful if you're trying to cast dynamically:
class Converter {
public $type = 'int';
public function cast(&$val){ settype($val, $this->type); }
}
$c = new Converter();
$arr = explode(",","1,2,3,0");
array_walk($arr,array($c, 'cast'));
print_r($arr);
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 0
)
// now using a bool
$c->type = 'bool';
$arr = explode(",","1,2,3,0");
array_walk($arr,array($c, 'cast'));
var_dump($arr); // using var_dump because the output is clearer.
array(4) {
[0]=>
bool(true)
[1]=>
bool(true)
[2]=>
bool(true)
[3]=>
bool(false)
}
Since $thestring is an string then you will get an array of strings.
Just add (int) in front of the exploded values.
Or use the array_walk function:
$arr = explode(',', $thestring);
array_walk($arr, 'intval');
$thestring = "1,2,3,8,a,b,2";
$newArray = array();
$theArray = explode(",", $thestring);
print_r($theArray);
foreach ($theArray as $theData) {
if (is_numeric($theData)) {
$newArray[] = $theData;
}
}
print_r($newArray);
// Output
Original array
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 8 [4] => a [5] => b [6] => 2 )
Numeric only array
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 8 [4] => 2 )
$arr=explode(',', $thestring);
$newstr = '';
foreach($arr as $key=>$val){
$newstr .= $val;
}

How do you split a string into word pairs?

I am trying to split a string into an array of word pairs in PHP. So for example if you have the input string:
"split this string into word pairs please"
the output array should look like
Array (
[0] => split this
[1] => this string
[2] => string into
[3] => into word
[4] => word pairs
[5] => pairs please
[6] => please
)
some failed attempts include:
$array = preg_split('/\w+\s+\w+/', $string);
which gives me an empty array, and
preg_match('/\w+\s+\w+/', $string, $array);
which splits the string into word pairs but doesn't repeat the word. Is there an easy way to do this? Thanks.
Why not just use explode ?
$str = "split this string into word pairs please";
$arr = explode(' ',$str);
$result = array();
for($i=0;$i<count($arr)-1;$i++) {
$result[] = $arr[$i].' '.$arr[$i+1];
}
$result[] = $arr[$i];
Working link
If you want to repeat with a regular expression, you'll need some sort of look-ahead or look-behind. Otherwise, the expression will not match the same word multiple times:
$s = "split this string into word pairs please";
preg_match_all('/(\w+) (?=(\w+))/', $s, $matches, PREG_SET_ORDER);
$a = array_map(
function($a)
{
return $a[1].' '.$a[2];
},
$matches
);
var_dump($a);
Output:
array(6) {
[0]=>
string(10) "split this"
[1]=>
string(11) "this string"
[2]=>
string(11) "string into"
[3]=>
string(9) "into word"
[4]=>
string(10) "word pairs"
[5]=>
string(12) "pairs please"
}
Note that it does not repeat the last word "please" as you requested, although I'm not sure why you would want that behavior.
You could explode the string and then loop through it:
$str = "split this string into word pairs please";
$strSplit = explode(' ', $str);
$final = array();
for($i=0, $j=0; $i<count($strSplit); $i++, $j++)
{
$final[$j] = $strSplit[$i] . ' ' . $strSplit[$i+1];
}
I think this works, but there should be a way easier solution.
Edited to make it conform to OP's spec. - as per codaddict
$s = "split this string into word pairs please";
$b1 = $b2 = explode(' ', $s);
array_shift($b2);
$r = array_map(function($a, $b) { return "$a $b"; }, $b1, $b2);
print_r($r);
gives:
Array
(
[0] => split this
[1] => this string
[2] => string into
[3] => into word
[4] => word pairs
[5] => pairs please
[6] => please
)

Split a string on every third instance of character

How can I explode a string on every third semicolon (;)?
example data:
$string = 'piece1;piece2;piece3;piece4;piece5;piece6;piece7;piece8;';
Desired output:
$output[0] = 'piece1;piece2:piece3;'
$output[1] = 'piece4;piece5;piece6;'
$output[2] = 'piece7;piece8;'
I am sure you can do something slick with regular expressions, but why not just explode the each semicolor and then add them three at a time.
$tmp = explode(";", $string);
$i=0;
$j=0;
foreach($tmp as $piece) {
if(! ($i++ %3)) $j++; //increment every 3
$result[$j] .= $piece;
}
Easiest solution I can think of is:
$chunks = array_chunk(explode(';', $input), 3);
$output = array_map(create_function('$a', 'return implode(";",$a);'), $chunks);
Essentially the same solution as the other ones that explode and join again...
$tmp = explode(";", $string);
while ($tmp) {
$output[] = implode(';', array_splice($tmp, 0, 3));
};
$string = "piece1;piece2;piece3;piece4;piece5;piece6;piece7;piece8;piece9;";
preg_match_all('/([A-Za-z0-9\.]*;[A-Za-z0-9\.]*;[A-Za-z0-9\.]*;)/',$string,$matches);
print_r($matches);
Array
(
[0] => Array
(
[0] => piece1;piece2;piece3;
[1] => piece4;piece5;piece6;
[2] => piece7;piece8;piece9;
)
[1] => Array
(
[0] => piece1;piece2;piece3;
[1] => piece4;piece5;piece6;
[2] => piece7;piece8;piece9;
)
)
Maybe approach it from a different angle. Explode() it all, then combine it back in triples. Like so...
$str = "1;2;3;4;5;6;7;8;9";
$boobies = explode(";", $array);
while (!empty($boobies))
{
$foo = array();
$foo[] = array_shift($boobies);
$foo[] = array_shift($boobies);
$foo[] = array_shift($boobies);
$bar[] = implode(";", $foo) . ";";
}
print_r($bar);
Array
(
[0] => 1;2;3;
[1] => 4;5;6;
[2] => 7;8;9;
)
Here's a regex approach, which I can't say is all too good looking.
$str='';
for ($i=1; $i<20; $i++) {
$str .= "$i;";
}
$split = preg_split('/((?:[^;]*;){3})/', $str, -1,
PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
Output:
Array
(
[0] => 1;2;3;
[1] => 4;5;6;
[2] => 7;8;9;
[3] => 10;11;12;
[4] => 13;14;15;
[5] => 16;17;18;
[6] => 19;
)
Another regex approach.
<?php
$string = 'piece1;piece2;piece3;piece4;piece5;piece6;piece7;piece8';
preg_match_all('/([^;]+;?){1,3}/', $string, $m, PREG_SET_ORDER);
print_r($m);
Results:
Array
(
[0] => Array
(
[0] => piece1;piece2;piece3;
[1] => piece3;
)
[1] => Array
(
[0] => piece4;piece5;piece6;
[1] => piece6;
)
[2] => Array
(
[0] => piece7;piece8
[1] => piece8
)
)
Regex Split
$test = ";2;3;4;5;6;7;8;9;10;;12;;14;15;16;17;18;19;20";
// match all groups that:
// (?<=^|;) follow the beginning of the string or a ;
// [^;]* have zero or more non ; characters
// ;? maybe a semi-colon (so we catch a single group)
// [^;]*;? again (catch second item)
// [^;]* without the trailing ; (to not capture the final ;)
preg_match_all("/(?<=^|;)[^;]*;?[^;]*;?[^;]*/", $test, $matches);
var_dump($matches[0]);
array(7) {
[0]=>
string(4) ";2;3"
[1]=>
string(5) "4;5;6"
[2]=>
string(5) "7;8;9"
[3]=>
string(6) "10;;12"
[4]=>
string(6) ";14;15"
[5]=>
string(8) "16;17;18"
[6]=>
string(5) "19;20"
}
<?php
$str = 'piece1;piece2;piece3;piece4;piece5;piece6;piece7;piece8;';
$arr = array_map(function ($arr) {
return implode(";", $arr);
}, array_chunk(explode(";", $str), 3));
var_dump($arr);
outputs
array(3) {
[0]=>
string(20) "piece1;piece2;piece3"
[1]=>
string(20) "piece4;piece5;piece6"
[2]=>
string(14) "piece7;piece8;"
}
Similar to #Sebastian's earlier answer, I recommend preg_split() with a repeated pattern. The difference is that by using a non-capturing group and appending \K to restart the fullstring match, you can spare writting the PREG_SPLIT_DELIM_CAPTURE flag.
Code: (Demo)
$string = 'piece1;piece2;piece3;piece4;piece5;piece6;piece7;piece8;';
var_export(preg_split('/(?:[^;]*;){3}\K/', $string, 0, PREG_SPLIT_NO_EMPTY));
A similar technique for splitting after every 2 things can be found here. That snippet actually writes the \K before the last space character so that the trailing space is consumed while splitting.

Categories