Php multiple delimiters in explode [duplicate]
Asked Answered
K

12

189

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;
}
Kenogenesis answered 10/2, 2011 at 9:43 Comment(1)
I never saw a question with people giving answers like "How about this", "What about that"Utile
C
351

Try about using:

$output = preg_split('/ (@|vs) /', $input);
Callow answered 10/2, 2011 at 9:45 Comment(9)
Amazing. i wonder how this chalks up against explode() on single argumentsBakehouse
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)Callow
Note that some characters needs to be escaped to work (such as /, ?). For example: preg_split("/(\/|\?|=)/", $foo);.Costanzia
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')Foxed
Not with one step, but you can achieve this by proper designCallow
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)Avocado
Spaces was there to distingush betweeb "vs" as separate string with "vs" as part of some (Maybe strange) word - try to replaces space with \sCallow
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'.)Febricity
@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.Demasculinize
S
85

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

Sigmoid answered 10/2, 2011 at 9:48 Comment(5)
Easy solution, ended up using it for Json code to replace "}}" by "|". Dirty but efficient :) !Fancy
this won't work properly when one delimiter is a superset of the other (e.g. (@|@!) case)Beefwitted
@vaxquis Yes it will. str_replace('@!', '@',$str); Make sure you start with the most unique delimiter.Sigmoid
@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.Beefwitted
@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.Tinatinamou
E
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

Euh answered 4/1, 2015 at 16:28 Comment(1)
Love this answers use of str_replace. Very clever and clean solution.Enemy
K
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!

Klaraklarika answered 24/10, 2012 at 20:6 Comment(0)
H
12

Wouldn't strtok() work for you?

Homeward answered 10/2, 2011 at 9:46 Comment(1)
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 charactersRafferty
M
10

Simply you can use the following code:

$arr=explode('sep1',str_replace(array('sep2','sep3','sep4'),'sep1',$mystring));
Maize answered 8/3, 2014 at 11:45 Comment(1)
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.Demasculinize
M
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/

Melodious answered 7/6, 2016 at 9:54 Comment(4)
Now that's a silly solution with a possibility to return false resultsRasla
What else do you propose? It would be great if you can tell me what's wrong?Melodious
Propose? Me? Isn't here the accepted answer at the top? Concise, clear and without errors?Rasla
Agree, thanks common sense 😊Melodious
P
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);
}
Peccadillo answered 14/10, 2014 at 11:37 Comment(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.Demasculinize
Correction: $delims = (array)$delims; can be unconditionally declared.Demasculinize
Nope: paste.pics/GD6BO paste.pics/GD6BUPeccadillo
What are you "nope"ing? You didn't show your adjusted code.Demasculinize
As shown here, your snippet is unnecessarily convoluted.Demasculinize
M
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

Marcy answered 22/2, 2019 at 14:47 Comment(0)
A
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?

Ammonic answered 10/2, 2011 at 9:47 Comment(0)
I
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.

Indophenol answered 10/2, 2011 at 9:49 Comment(0)
H
-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.

Humming answered 30/12, 2014 at 18:9 Comment(1)
This answer appears to completely ignore the asker's context and requirements.Demasculinize

© 2022 - 2024 — McMap. All rights reserved.