5

Suppose I have this following string :

5+6-5*3/2+4

I need to split the string into two arrays: first array containing the integers, second array containing the operators from the string.

I have used the preg_split() function, like this

preg_split("/[^0-9]+/", $str)

and have successfully completed the task, but I've been told to use the explode() and implode() functions. I tried using them, but now I'm totally confused about how to get the desired arrays using them.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Tango Alpha
  • 157
  • 3
  • There is no method in the String class for what you want, you will have to write our own function. Like you will have to check charterer of string and check whether is Integer or spacial character. – Bhavishya Prajapati Apr 25 '17 at 10:29

5 Answers5

9

Here preg_match can also help you out. You can do it with preg_split as well. preg_match is a better solution if in case you have string like this 5+6-(5*3)/2+4 then preg_split result also gives you ( and ) as well. Here we are using array_map for iterating and preventing 0's, which might get removed with array_filter.

Try this code snippet here

Solution 1: using preg_match

Regex: (\d+)|([+-\/\*]) This will match either one or more digits or any arithmetic symbol.

<?php
ini_set('display_errors', 1);
$str = "5+6-5*3/2+4+0";
preg_match_all("/(\d+)|([+-\/\*])/", $str,$matches);

$digits=array();
array_map(function($value) use(&$digits){
    if($value!=="" && $value!==null && $value!==false)
    {
        $digits[]=$value;
    }
}, $matches[1]);

$symbols=array();
array_map(function($value) use(&$symbols){
    if($value!=="" && $value!==null && $value!==false)
    {
        $symbols[]=$value;
    }
}, $matches[2]);

print_r($digits);
print_r($symbols);

Try this code snippet here

Solution 2: using preg_split

Here we are spliting string on digits (\d+) and symbols [+-\/\*]

<?php

ini_set('display_errors', 1);
$str = "5+6-5*3/2+4+0";
$symbols=preg_split("/(\d+)/", $str);
$digits=preg_split("/([+-\/\*])/", $str);

$symbols=  array_filter($symbols);
print_r($digits);
print_r($symbols);
Sahil Gulati
  • 15,028
  • 4
  • 24
  • 42
1

Try this work for me

First Method

$str = "5+6-5*3/2+4";


preg_match_all('!\d+!', $str, $matches);
preg_match_all('/[^0-9]+/', $str, $matches2);

print_r($matches[0]); //integers
echo '<br/>';
print_r($matches2[0]); //operators

Second Method

function multiexplode ($delimiters,$string) {
    $ready = str_replace($delimiters, $delimiters[0], $string);
    $launch = explode($delimiters[0], $ready);
    return  $launch;
}

$resultArray = multiexplode(array('+','-','/','*'), $str);
print_r($resultArray);
echo '<br/>';
$resultArray1 = array_filter(multiexplode(range(0,9), $str));
print_r($resultArray1);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Bachcha Singh
  • 3,850
  • 3
  • 24
  • 38
1

Two regex scans of the string with preg_split(): (Demo)

$digits = preg_split("/\D+/", $str, 0, PREG_SPLIT_NO_EMPTY);
$symbols = preg_split("/\d+/", $str, 0, PREG_SPLIT_NO_EMPTY);

One regex scan of the string with preg_split(): (Demo)

foreach (preg_split("/(\d+)/", $str, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $string) {
    if (ctype_digit($string)) {
        $digits[] = $string;
    } else {
        $symbols[] = $string;
    }
}

One regex scan of the string with preg_match_all(): (Demo)

preg_match_all("/(\d+)|(\D+)/", $str, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
    if ($match[1] !== '') {
        $digits[] = $match[1];
    } else {
        $symbols[] = $match[2];
    }
}

In most cases, the data volume is so small that efficiency is not worth benchmarking. If this is true for your project, then choose the technique that you find easiest to read and maintain.


Explanations

A regex-based solution is the only sensibly efficient/direct way to extract the desired substrings from the input string.

We can only assume that your input string is only comprised of digits and symbols (no other characters). If there are other characters, then the patterns will need adjustment.

With capturing the digits, there are four basic patterns to choose from: \d+, [^\D], [0-9]+, [^-+*/]+ All four patterns take an equal amount of "steps", so the deciding factor is pattern brevity and \d+ wins.

With capturing the symbols, there are four basic patterns: \D, [^\d], [^0-9],[-+/*] All four patterns take an equal amount of "steps", so again the deciding factor is pattern brevity and \D wins.

For best testing, I will be using $str = "50+16-0*387/2+49"; as my input as it includes a zero and multi-digit integers.


A critique of Sahil's answer for the benefit of researchers who may be biased by the vote count:

  1. [+-\/\*] is teaching bad character class construction. This pattern is saying match any of the 6 following listed characters (but only 4 symbols are required for this task):

    • any character from hyphen to forward slash (+, ,, -, ., /)
    • a literal asterisk (which does not need to be escaped)

    In other words, the hyphen in the character class is not treated literally, it is creating a range of acceptable characters.

  2. Using array_map() but ignoring its return value indicates an inappropriate use of the function. It would be more sensible to use array_walk() but the necessary syntax is more verbose and harder to read. array_filter() or array_reduce() could also be used to return the filtered arrays to their appropriate result variable, but this would mean performing two loops over the same data. A foreach() (as a single pass) is going to be the cleanest way to populate the two result arrays.

  3. The preg_split() calls are vulnerable to generating empty element because there is no PREG_SPLIT_NO_EMPTY flag used.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
0

Try This i am post another Method

<?php
    error_reporting(0);
    $str = "5+6-5*3/2+4";
    $array_opartor=preg_split("/[0-9]/", $str);
    $array_integer=preg_split("/[^0-9]+/", $str);
$two_array=array_merge($array_opartor,$array_integer);
$all_operator=array();
$all_numeric=array();
foreach($two_array as $array_results)
{
    if(is_numeric($array_results))
    {
     array_push($all_numeric,$array_results);
    }
    else if($array_results!="")
    {
    array_push($all_operator,$array_results);
    }
}
print_r($all_operator); // View All operator in array
echo "<br/>";
print_r($all_numeric); // View All Numeric value in Array   
?>

Second Solution

<?php
    error_reporting(0);
    $str = "5+6-5*3/2+4";
    $array_opartor=preg_split("/[0-9]/", $str);
    $array_integer=preg_split("/[^0-9]+/", $str);
    $all_operator=array_filter($array_opartor);//use thi fo remove all null value in array
    print_r($all_operator); // View All operator in array
    echo "<br/>";
    print_r($array_integer); // View All Numeric value in Array
    ?>
Waseem Ahmad
  • 303
  • 3
  • 10
  • Downvoted because: you have offered no explanation with your code; your code is inefficient; your output does not provide two arrays as desired by the OP; and finally your code produces 2 NOTICES because of undefined variables. This isn't trolling, this is feedback. If I was a troll I wouldn't be leaving a comment. Please consider editing your question to create a new, unique, efficient, valuable, complete answer; or if you cannot or do not wish to do this, please delete your answer to reduce page bloat. – mickmackusa Apr 27 '17 at 22:46
  • I am afraid I cannot remove my downvote because your edit is a duplicate of Sahil Gulati's earlier posted answer. It may be best to simply delete your answer, because I believe all of the best / most efficient answers have been provided. (you are welcome to prove me wrong if you can create a new, unique, efficient, valuable method.) – mickmackusa Apr 29 '17 at 07:28
0

I like the way implemented by @Sahil Gulati, but it does not fulfill your requirement of using explode - implode.

Here is my code for that:

function solution5($S){
    $return['digits'] = multipleExplode(array('+','-','/','*'), $S);
    $return['symbols']= array_filter(multipleExplode(range(0,9), $S));
    return $return;
}

function multipleExplode($del,$str) {
    $passStr = str_replace($del, $del[0], $str);
    $returnArr = explode($del[0], $passStr);
    return  $returnArr;
}

var_dump(solution5("5+6-5*3/2+4"));

Maybe this helps you to solve your query.

Shaunak Shukla
  • 2,347
  • 2
  • 18
  • 29