分解一个字符串,返回一个数组,为每个键删除一个字符串

时间:2018-10-28 15:36:05

标签: php php-7

假设我们有字符串快速的棕狐跳过了懒狗

我想要一个返回以下内容的数组(每次删除一个单词)。

array:9 [▼
  0 => "The quick brown fox jumps over the lazy dog"
  1 => "quick brown fox jumps over the lazy dog"
  2 => "brown fox jumps over the lazy dog"
  3 => "fox jumps over the lazy dog"
  4 => "jumps over the lazy dog"
  5 => "over the lazy dog"
  6 => "the lazy dog"
  7 => "lazy dog"
  8 => "dog"
]

我迅速启动了执行此操作的以下功能。

function wordsToArr($str)
    {

           $words =[];
           $ex_str =explode(' ',$str);


           foreach($ex_str as $k=>$v){

              $words[] =implode(' ',$ex_str);

              unset($ex_str[$k]);
            }

           return $words;
    }

现在我的问题是:有没有一种更快的方法,性能明智的方法呢?

更新根据要求,我进行了基准测试。还尝试了以下功能:

function wordsToArr2($str)
    {

        $words =[$str];
        while($pos =strpos ( $str , ' ')){

            $str=substr($str,($pos+1));
            $words[] =$str;
        }

        return $words;

    }

使用此脚本对其进行基准测试:https://gist.github.com/blongden/2352583

结果:

Explode (wordsToArr) string run: 317,505/sec
strpos/substr (wordsToArr2) run: 542,725/sec

我的问题仍然存在,是否还有其他功能可以使速度更快?

1 个答案:

答案 0 :(得分:1)

看起来strpossubstr可能是表现最稳定的。

但是,另一种选择是,由于您已经有一个单词列表,因此可以使用串联来代替删除每个单词。减少每次迭代的函数调用次数。

示例:https://3v4l.org/j5YMm

$str = 'The quick brown fox jumps over the lazy dog';
$base = array_reverse(explode(' ', $str));
$words = [$placeholder = array_shift($base)];
foreach($base as $word) {
    $words[] = $placeholder = $word . ' ' . $placeholder;
}
$words = array_reverse($words);
print_r($words);

结果

数字在3v4l上非常不一致-您自己的服务器和PHP版本上的基准测试

PHP 5.6.38

implode 100 times in: 0.00047302/sec
strpos 100 times in:  0.00035501/sec
concat 100 times in:  0.00034595/sec

返回

Array
(
    [0] => The quick brown fox jumps over the lazy dog
    [1] => quick brown fox jumps over the lazy dog
    [2] => brown fox jumps over the lazy dog
    [3] => fox jumps over the lazy dog
    [4] => jumps over the lazy dog
    [5] => over the lazy dog
    [6] => the lazy dog
    [7] => lazy dog
    [8] => dog
)

注意 还有很多实现串联的方法。

您可以将array_shift替换为需要array_pop重新索引数组的$base = explode(' ', $str); $words = [$placeholder = array_pop($base)]; $base = array_reverse($base); ,从而稍微降低操作码的复杂性。

foreach

您还可以在$base = array_reverse(explode(' ', $str)); $s = ''; foreach ($base as $i => $w) { $words[] = $s = ($i === 0 ? $w : $w . ' ' . $s); } 内的键上使用条件,以确定是否应使用级联,而不会造成性能损失。

for count()

已更新

作为减少操作码调用次数的另一种方法,可以使用$i--$l = count($base) - 1;来反向处理数组。 可以选择将end($base); $l = key($base);替换为array_key_last,或将$base = explode(' ', $str); $l = count($base)-1; $words = [$placeholder = $base[$l--]]; for ($i=$l; $i>=0;$i--) { $words[] = $placeholder = $base[$i] . ' ' . $placeholder; } $words = array_reverse($words); print_r($words); 用于PHP 7.3

示例https://3v4l.org/VfJku

strpos 100 times in: 0.00043607/sec
concat 100 times in: 0.00044894/sec
end/key 100 times in: 0.00037289/sec
count-- 100 times in: 0.00036097/sec

PHP 5.6.38

TYPE