188

I have a problem, I have a string array, and I want to explode in different delimiter. For Example

$example = 'Appel @ Ratte';
$example2 = 'apple vs ratte'

and I need an array which is explode in @ or vs.

I already wrote a solution, but If everybody have a better solution please post here.

private function multiExplode($delimiters,$string) {
    $ary = explode($delimiters[0],$string);
    array_shift($delimiters);
    if($delimiters != NULL) {
        if(count($ary) <2)                      
            $ary = $this->multiExplode($delimiters, $string);
    }
    return  $ary;
}
Nanne
  • 64,065
  • 16
  • 119
  • 163
Mokus
  • 10,174
  • 18
  • 80
  • 122

12 Answers12

348

Try about using:

$output = preg_split('/ (@|vs) /', $input);
SergeS
  • 11,533
  • 3
  • 29
  • 35
  • Amazing. i wonder how this chalks up against `explode()` on single arguments – Ascherer May 21 '13 at 05:56
  • 8
    It doesn't matter, if you want to make large system with hard string parsing, the most effective way is own parser. Oterwise it doesn't have much effect on system speed, but you preffer to use easiest way for you (To be money effective) – SergeS May 21 '13 at 05:59
  • 12
    Note that some characters needs to be escaped to work (such as `/`, `?`). For example: `preg_split("/(\/|\?|=)/", $foo);`. – kenorb Apr 24 '15 at 19:11
  • preg_split returns indexed array. It possible to return associative? For example `$str='/x/1/2/3/4/5/y/100/200/z/777'; preg_split("/(x|y|z|)/", $str);` and to see `array('x'=>'1/2/3/4/5', 'y'=>'100/200', 'z'=>'777')` – LINKeRxUA Oct 02 '15 at 15:00
  • Not with one step, but you can achieve this by proper design – SergeS Oct 03 '15 at 15:45
  • 7
    I found having the spaces in between the `/ (` and `) /` stopped preg_split from working. I had to remove the spaces and then it worked as expected (using PHP 7) – Boardy Mar 11 '18 at 00:31
  • 1
    Spaces was there to distingush betweeb "vs" as separate string with "vs" as part of some (Maybe strange) word - try to replaces space with \s – SergeS Mar 12 '18 at 06:31
  • Since this solution requires spaces around the two delimiters, it will not split the string 'banjo vs. guitar' (vs with period). This would require replacing the two space ('/ ' & ' /') with a set of delimiters, like '[ \.]+'. (The + allows matching 'vs period space'.) – Guy Gordon Jun 13 '19 at 14:00
  • 1
    @GuyGordon Yes, if you change the delimiting substring, of course this specifically designed pattern will fail. Why would you bother to make such a comment. Maybe people would have an easier time of adjusting this answer's advice for their own project if this answer actually explained how it works and what it does. In other words, code-only answers are low-value on Stack Overflow because they miss an opportunity to educate/empower the asker and thousands of future researchers. – mickmackusa Mar 12 '22 at 10:00
84

You can take the first string, replace all the @ with vs using str_replace, then explode on vs or vice versa.

Ry-
  • 218,210
  • 55
  • 464
  • 476
John Ballinger
  • 7,380
  • 5
  • 41
  • 51
  • 1
    Easy solution, ended up using it for Json code to replace "}}" by "|". Dirty but efficient :) ! – Baldráni Nov 05 '15 at 09:59
  • this won't work properly when one delimiter is a superset of the other (e.g. `(@|@!)` case) –  Jun 29 '18 at 12:16
  • 2
    @vaxquis Yes it will. str_replace('@!', '@',$str); Make sure you start with the most unique delimiter. – John Ballinger Aug 14 '18 at 05:12
  • @JohnBallinger No, it won't - you proposed *another* solution, which clearly shows the *original* solution *won't* work properly and that your idea is flawed. Imagine you don't know which one is the superset of another. You'd have to create another line of code to check for that etc. While I hate regexes in general, this is a case when it's the best solution in terms of maintainability and simplicity. –  Aug 14 '18 at 11:16
  • 2
    @vaxquis - though you brought up a good point, it should be noted that there will always be issues with the case you mentioned even using `preg_split()`. Consider the difference in output of `preg_split('/(@|@!)/','A@B@!C')` vs `preg_split('/(@!|@)/','A@B@!C')`. The order of the delimiters changes the results. John's solution performs just as well as long as you are careful about how you order your array of delimiters. – But those new buttons though.. Dec 07 '18 at 05:32
67
function multiexplode ($delimiters,$string) {

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

$text = "here is a sample: this text, and this will be exploded. this also | this one too :)";


$exploded = multiexplode(array(",",".","|",":"),$text);

print_r($exploded);

//And output will be like this:
// Array
// (
//    [0] => here is a sample
//    [1] =>  this text
//    [2] =>  and this will be exploded
//    [3] =>  this also 
//    [4] =>  this one too 
//    [5] => )
// )

Source: php@metehanarslan at php.net

kenorb
  • 155,785
  • 88
  • 678
  • 743
parts2eu
  • 864
  • 7
  • 11
14

How about using strtr() to substitute all of your other delimiters with the first one?

private function multiExplode($delimiters,$string) {
    return explode(
        $delimiters[0],
        strtr(
            $string,
            array_combine(
                array_slice(    $delimiters, 1  ),
                array_fill(
                    0,
                    count($delimiters)-1,
                    array_shift($delimiters)
                )
            )
        )
    );
}

It's sort of unreadable, I guess, but I tested it as working over here.

One-liners ftw!

Aubry
  • 141
  • 1
  • 2
12

Wouldn't strtok() work for you?

Ry-
  • 218,210
  • 55
  • 464
  • 476
Mchl
  • 61,444
  • 9
  • 118
  • 120
  • 2
    seeing his delimitter is 'vs', this may not work as php docu says: strtok() splits a string (str) into smaller strings (tokens), with each token being delimited by any character from token. and 'vs' contains two characters – mikewasmike Dec 17 '15 at 19:03
10

Simply you can use the following code:

$arr=explode('sep1',str_replace(array('sep2','sep3','sep4'),'sep1',$mystring));
Samer Ata
  • 1,027
  • 1
  • 12
  • 11
  • This answer makes no attempt to satisfy the question asked. Why have you completely ignored the asker's provided data and required output? I don't understand why this code-only answer has such a score. – mickmackusa Mar 12 '22 at 09:52
6

You can try this solution, It works great.

It replaces all the delimiters with one common delimiter "chr(1)" and then uses that to explode the string.

function explodeX( $delimiters, $string )
{
    return explode( chr( 1 ), str_replace( $delimiters, chr( 1 ), $string ) );
}
$list = 'Thing 1&Thing 2,Thing 3|Thing 4';

$exploded = explodeX( array('&', ',', '|' ), $list );

echo '<pre>';
print_r($exploded);
echo '</pre>';

Source : http://www.phpdevtips.com/2011/07/exploding-a-string-using-multiple-delimiters-using-php/

Mayur Chauhan
  • 682
  • 1
  • 12
  • 25
2

I do it this way...

public static function multiExplode($delims, $string, $special = '|||') {

    if (is_array($delims) == false) {
        $delims = array($delims);
    }

    if (empty($delims) == false) {
        foreach ($delims as $d) {
            $string = str_replace($d, $special, $string);
        }
    }

    return explode($special, $string);
}
Vaci
  • 161
  • 1
  • 5
  • `$delims = array($delims);` can be unconditionally called to ensure that the variable is array-type. The `empty()` check is completely unnecessary because the variable is guaranteed to be declared and if it is empty, then the foreach will not be entered. Making iterated calls of `str_replace()` is unnecessary because the first parameter of `str_replace()` will happily receive an array. There isn't much that I would keep in this code-only answer. See @MayurChauhan's refined version of this answer. – mickmackusa Mar 12 '22 at 09:56
  • Correction: `$delims = (array)$delims;` can be unconditionally declared. – mickmackusa Mar 13 '22 at 11:54
  • Nope: https://paste.pics/GD6BO https://paste.pics/GD6BU – Vaci Mar 14 '22 at 19:19
  • What are you "nope"ing? You didn't show your adjusted code. – mickmackusa Mar 14 '22 at 22:26
  • As shown [here](https://stackoverflow.com/a/27767665/2943403), your snippet is unnecessarily convoluted. – mickmackusa Mar 14 '22 at 22:36
2

How about this?

/**
 * Like explode with multiple delimiters. 
 * Default delimiters are: \ | / and ,
 *
 * @param string $string String that thould be converted to an array.
 * @param mixed $delimiters Every single char will be interpreted as an delimiter. If a delimiter with multiple chars is needed, use an Array.
 * @return array. If $string is empty OR not a string, return false
 */
public static function multiExplode($string, $delimiters = '\\|/,') 
{
  $delimiterArray = is_array($delimiters)?$delimiters:str_split($delimiters);
  $newRegex = implode('|', array_map (function($delimiter) {return preg_quote($delimiter, '/');}, $delimiterArray));
  return is_string($string) && !empty($string) ? array_map('trim', preg_split('/('.$newRegex.')/', $string, -1, PREG_SPLIT_NO_EMPTY)) : false;
}

In your case you should use an Array for the $delimiters param. Then it is possible to use multiple chars as one delimiter.

If you don't care about trailing spaces in your results, you can remove the array_map('trim', [...] ) part in the return row. (But don't be a quibbler in this case. Keep the preg_split in it.)

Required PHP Version: 5.3.0 or higher.

You can test it here

A.F.
  • 41
  • 7
1

You are going to have some problems (what if you have this string: "vs @ apples" for instance) using this method of sepparating, but if we start by stating that you have thought about that and have fixed all of those possible collisions, you could just replace all occurences of $delimiter[1] to $delimiter[n] with $delimiter[0], and then split on that first one?

Nanne
  • 64,065
  • 16
  • 119
  • 163
1

If your delimiter is only characters, you can use strtok, which seems to be more fit here. Note that you must use it with a while loop to achieve the effects.

Ry-
  • 218,210
  • 55
  • 464
  • 476
Hoàng Long
  • 10,746
  • 20
  • 75
  • 124
-1

This will work:

$stringToSplit = 'This is my String!' ."\n\r". 'Second Line';
$split = explode (
  ' ', implode (
    ' ', explode (
      "\n\r", $stringToSplit
    )
  )
);

As you can see, it first glues the by \n\r exploded parts together with a space, to then cut it apart again, this time taking the spaces with him.

Xesau
  • 161
  • 1
  • 9