数组分隔符引起的“爆炸”问题

21

有没有一种使用分隔符数组的方法来执行 explode() 函数?

PHP 手册:

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

是否有一种方法可以使用 array $delimiter 而不会对性能产生太大影响,而不是使用 string $delimiter?

6个回答

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

太棒了,这个解决方案既聪明又简单,赞! - Somal Somalski
很不错,但我更喜欢Ale的版本。这个会出现尾随第一个分隔符的故障。 - user568109
@user568109 我相信我只是缺乏想象力,但我没有看到这个bug/glitch。 - Joel Mellon
在研究了这个页面很长时间后,我猜测65Fbef05的答案已经被更改以解决这个错误。 - Joel Mellon
@sudopeople 我其实从来没有解决user568109的问题,我最后一次修改答案是在他们发表评论之前很久。我不太确定他们的意思是什么。 - 65Fbef05
显示剩余2条评论

31

7
例如:print_r(preg_split("/[,. ]/", "0 1,2.3"));将会给你Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3) - sirhc
2
print_r(preg_split("/[,\. ]/", "0 1,2.3")); 你是说这个吧:) 谢谢,我想这应该是最好的方法了。 - JoeC

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

这是对 @65Fbef05 的代码进行了优化。我们使用第一个定界符,因为原始字符串中可能会使用 "+delim+"


0
以上的建议如果第一个分隔符后面包含了第一个分隔符的字符,那么就不会起作用。例如,如果您想使用换行符作为分隔符,但是您不确定输入是否使用 \r\n、\r 或只有 \n,那么您不能使用上述方法。
$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)));

这将输出:

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) ""
}

如果你计划进行字符串比较,这并不理想。相反,你需要变得更加复杂。下面我所写的可能不是最有效和简洁的,但它能够完成任务。

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

它将输出以下内容:
array(7) {
  [0]=>
  string(3) "___"
  [1]=>
  string(3) "___"
  [2]=>
  string(3) "___"
  [3]=>
  string(3) "___"
  [4]=>
  string(3) "___"
  [5]=>
  string(3) "___"
  [6]=>
  string(0) ""
}

来玩一下:https://3v4l.org/bJOkI


0
采用了@65Fbef05的答案,并将其转换为函数。注意:这与原始的explode函数一样区分大小写。
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);
}

并且进行了单元测试(使用PHPUnit),因为我对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'],
    ];
}

-2

PHP的explode方法不支持多个分隔符,因此您无法将数组传递给它。 另外,您正在解析什么类型的字符串,其中有多个分隔符?您最好的选择是循环遍历您的分隔符,并重新拆分一些已经拆分的字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接