php - How to split a string into two arrays using explode-implode functions?


Keywords:php 


Question: 

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.


5 Answers: 

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

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

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

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

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

Here is a Demo for both of my methods below.


A CLEAN TWO-LINER:

This perfects Sahil's second method by implementing the shortest patterns, removing the capturing parentheses, using null for unlimited splits, and flagging with PREG_SPLIT_NO_EMPTY on preg_split()):

$digits=preg_split("/[^\d]/",$str,null,PREG_SPLIT_NO_EMPTY);
$symbols=preg_split("/\d+/",$str,null,PREG_SPLIT_NO_EMPTY);  // leaving NO_EMPTY flag in place though it would only come into play if the string began or ended with a symbol (like say, "-5+3" or something)

Note: Bachcha Singh takes a similar two-line approach using preg_match_all() but this is slightly less efficient because it generates a true/false boolean in addition to a multi-dimensional array, where as my preg_split() approach simply generates a one-dimensional array.


A LESS READABLE ONE-LINER:

I also wrote a one-liner solution as a personal challenge that leverages: 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 the multi-line breakdown:

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 these respective arrays:

array('50','16','0','387','2','49')
array('+','-','*','/','+')
 

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.

 

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
    ?>