Exploding by Array of Delimiters
Asked Answered
M

6

23

Is there any way to explode() using an array of delimiters?

PHP Manual:

array explode ( string $delimiter , string $string [, int $limit ] )

Instead of using string $delimiter is there any way to use array $delimiter without affecting performance too much?

Mcatee answered 18/5, 2010 at 19:4 Comment(0)
E
31

Use preg_split() with an appropriate regex.

Endamoeba answered 18/5, 2010 at 19:7 Comment(2)
For example: print_r(preg_split("/[,. ]/", "0 1,2.3")); will give you Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3).Lambskin
print_r(preg_split("/[,\. ]/", "0 1,2.3")); you mean :) Thanks though, probably the best way I guess.Mcatee
M
59
$str = 'Monsters are SUPER scary, bro!';
$del = array('a', 'b', 'c');

// In one fell swoop...
$arr = explode( $del[0], str_replace($del, $del[0], $str) );
Minnaminnaminnie answered 6/12, 2010 at 20:36 Comment(7)
That should be faster than regexs, nice one.Donaldson
thats amazing, briliant and simple solution, kudos!Irvin
Great one, but I would prefer Ale's version. This glitches with trailing first delimiter.Comedian
@Comedian I'm sure I just lack the imagination but I don't see the bug/glitch in this.Cand
After studying this page for much too long, I'm guessing 65Fbef05's answer was changed to defeat the bug.Cand
@sudopeople I never addressed user568109's issue actually, last change to my answer was long before their comment. Not really sure what they meant.Minnaminnaminnie
@Minnaminnaminnie Well, I guess I'm in the same boat. I'm still not seeing any issue with your code.Cand
E
31

Use preg_split() with an appropriate regex.

Endamoeba answered 18/5, 2010 at 19:7 Comment(2)
For example: print_r(preg_split("/[,. ]/", "0 1,2.3")); will give you Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3).Lambskin
print_r(preg_split("/[,\. ]/", "0 1,2.3")); you mean :) Thanks though, probably the best way I guess.Mcatee
B
7
function explode_by_array($delim, $input) {
  $unidelim = $delim[0];
  $step_01 = str_replace($delim, $unidelim, $input); //Extra step to create a uniform value
  return explode($unidelim, $step_01);
}

That's improved @65Fbef05's code. We use first delimiter, because "+delim+" may be used in original string.

Bargain answered 7/7, 2012 at 19:36 Comment(0)
M
0

The above suggestions won't work if the delimiters after the first delimiter include characters from that first delimiter. For instance, if you want to use line breaks as delimiters, but you're not sure if your input uses \r\n, \r or just \n, you can't use the above methods.

$str = '___RN___RN___R___N___RN___RN';
$del = array('RN', 'R', 'N');

# This won't work if delimiters 2, 3, n include characters from delimiter 1
var_dump(explode( $del[0], str_replace($del, $del[0], $str)));

This will output:

array(11) {
  [0]=>
  string(4) "___R"
  [1]=>
  string(0) ""
  [2]=>
  string(4) "___R"
  [3]=>
  string(0) ""
  [4]=>
  string(4) "___R"
  [5]=>
  string(3) "___"
  [6]=>
  string(4) "___R"
  [7]=>
  string(0) ""
  [8]=>
  string(4) "___R"
  [9]=>
  string(0) ""
  [10]=>
  string(0) ""
}

Which isn't ideal if you're planning to do string comparisons. Instead, you'll need to get a bit more complex. What I have written below may not be the most efficient and succinct, but it does the trick.

# This, however, will work
function array_explode($delimiters, $string){
    if(!is_array(($delimiters)) && !is_array($string)){
        //if neither the delimiter nor the string are arrays
        return explode($delimiters,$string);
    } else if(!is_array($delimiters) && is_array($string)) {
        //if the delimiter is not an array but the string is
        foreach($string as $item){
            foreach(explode($delimiters, $item) as $sub_item){
                $items[] = $sub_item;
            }
        }
        return $items;
    } else if(is_array($delimiters) && !is_array($string)) {
        //if the delimiter is an array but the string is not
        $string_array[] = $string;
        foreach($delimiters as $delimiter){
            $string_array = array_explode($delimiter, $string_array);
        }
        return $string_array;
    }
}

var_dump(array_explode($del,$str));

It will output the following:

array(7) {
  [0]=>
  string(3) "___"
  [1]=>
  string(3) "___"
  [2]=>
  string(3) "___"
  [3]=>
  string(3) "___"
  [4]=>
  string(3) "___"
  [5]=>
  string(3) "___"
  [6]=>
  string(0) ""
}

Have a play: https://3v4l.org/bJOkI

Mopey answered 8/8, 2018 at 11:49 Comment(0)
B
0

Took @65Fbef05's answer, turned it into a func. Note: this is case sensitive like the original explode function.

public static function explodeByArray(array $delimeters, string $input): array {
    if($delimeters===[]){
        return [$input];
    }
    $unidelim = $delimeters[0];
    $step     = str_replace($delimeters, $unidelim, $input);
    return explode($unidelim, $step);
}

And unit tested (PHPUnit) as I'm always a bit suspicious of answers on stackoverflow:

/**
 * @dataProvider dataProviderForExplodeByArray
 * @param array  $delimeters
 * @param array  $expected
 * @param string $subject
 * @return void
 */
public function testExplodeByArray(array $delimeters, array $expected, string $subject='The quick brown fox jumps over the lazy dog'): void {
    self::assertSame($expected, explodeByArray($delimeters, $subject));
}

public function dataProviderForExplodeByArray(): array{
    return [
        [[], ['The quick brown fox jumps over the lazy dog']],
        [['zzz'], ['The quick brown fox jumps over the lazy dog']],
        [['the'], ['The quick brown fox jumps over ', ' lazy dog']],
        [['The quick brown fox jumps over the lazy dog'], ['', '']],
        [['The'], ['', ' quick brown fox jumps over the lazy dog']], 
        [['dog'], ['The quick brown fox jumps over the lazy ', '']], 
        [['the', 'quick'], ['The ', ' brown fox jumps over ', ' lazy dog']],
        [['quick', 'the'], ['The ', ' brown fox jumps over ', ' lazy dog']],
        [['quick', 'the', 'fox'], ['The ', ' brown ', ' jumps over ', ' lazy dog']],
        [['over', 'fox'], ['The ', 'y brown ', ' jumps ', ' the lazy ', ''], 'The foxy brown fox jumps over the lazy fox'],
    ];
}
Buckskins answered 14/9, 2022 at 8:54 Comment(0)
C
-2

php's explode method doesn't support multiple delimiters, so you can't pass it an array. Also, what kind of string are you parsing that has multiple delimiters? you're best bet would be to loop through your delimiters, and re-explode some of the exploded strings.

Coccidiosis answered 18/5, 2010 at 19:8 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.