分解一个字符串,返回一个数组,为每个键删除一个字符串
Exploding a string , returning an array removing one string for each key
假设我们有字符串 The quick brown fox jumps over the lazy dog
我想要一个返回数组,其中包含以下内容(每次删除一个单词)。
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;
}
现在我的问题是:是否有更快、性能更明智的方法来做到这一点?
UPDATE 根据要求,我执行了基准测试。还尝试了以下功能:
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
我的问题仍然存在,是否有任何其他功能可以使它更快?
看起来 strpos
和 substr
可能是表现最稳定的。
然而,由于您已经有了一个单词列表,因此您可以使用连接来代替删除每个单词,而不是删除每个单词。减少每次迭代的函数调用次数。
示例: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
Returns
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
用于 PHP 7.3
示例https://3v4l.org/VfJku
$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 5.6.38
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
假设我们有字符串 The quick brown fox jumps over the lazy dog
我想要一个返回数组,其中包含以下内容(每次删除一个单词)。
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;
}
现在我的问题是:是否有更快、性能更明智的方法来做到这一点?
UPDATE 根据要求,我执行了基准测试。还尝试了以下功能:
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
我的问题仍然存在,是否有任何其他功能可以使它更快?
看起来 strpos
和 substr
可能是表现最稳定的。
然而,由于您已经有了一个单词列表,因此您可以使用连接来代替删除每个单词,而不是删除每个单词。减少每次迭代的函数调用次数。
示例: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
Returns
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
用于 PHP 7.3
示例https://3v4l.org/VfJku
$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 5.6.38
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