A regular expression solution is the only reasonably effective way to extract the required substrings from the input string.
With the capture of numbers, four main patterns to choose from: \d+ , [0-9]+ , [^\*-\/]+ , [^+\-\*\/]+ All four patterns take an equal number of "steps", Therefore, the decisive factor is the pattern of brevity and \d+ wins.
When capturing characters, there are four main patterns: [^\d] , [^0-9] , [\*-\/] , [+-\/\*] All four patterns take an equal number of "steps", so the deciding factor is the brevity of the chart and [^\d] wins.
For both of my methods, I will use $str="50+16-0*387/2+49"; as my input, since it includes zero and multi-valued integers.
Below is the Demo for both of my methods below.
A CLEAN TWO-LINER :
This improves the second Sahil method by implementing the shortest patterns, removing the brackets to capture, using null for unlimited separation, and tagging with PREG_SPLIT_NO_EMPTY to preg_split () ):
$digits=preg_split("/[^\d]/",$str,null,PREG_SPLIT_NO_EMPTY); $symbols=preg_split("/\d+/",$str,null,PREG_SPLIT_NO_EMPTY);
Note. Bachcha Singh uses a similar two-line approach using preg_match_all() , but this is slightly less efficient because it generates a true / false boolean value in addition to a multidimensional array, where when my preg_split() method just generates a one-dimensional array.
LESS READ ONE LINE :
I also wrote a one-line solution as a personal call that uses: array_map () , preg_split() and is_numeric () :
array_map(function($v)use(&$digits,&$symbols){is_numeric($v)?$digits[]=$v:$symbols[]=$v;},preg_split("/(\d+|[^\d])\K/",$str,null,PREG_SPLIT_NO_EMPTY));
Here is a breakdown on several lines:
array_map( // iterate each value in the input array function($v)use(&$digits,&$symbols){ // $v is each value; declare output arrays as modifiable is_numeric($v)? // evaluate the value as a number $digits[]=$v: $symbols[]=$v; }, preg_split( // use a regex pattern to explode a string "/(\d+|[^\d])\K/", // split on each match, but \K stops the match being removed $str, // the input string null, // make unlimited splits PREG_SPLIT_NO_EMPTY // do not include any empty pattern matches ) );
Both methods will create the corresponding arrays:
array('50','16','0','387','2','49') array('+','-','*','/','+')