我用逗号分隔城市名称列表。 ($ cityNames可能包含100到500个名称)
$cityNames = "Chicago, San Diego, El Paso";
以下哪一项最好将逗号分隔列表转换为数组,同时还要考虑性能和准确性?
$cityNamesArray = explode(",", $cityNames);
或
$cityNamesArray = preg_split('/\s*,\s*/', $cityNames, -1, PREG_SPLIT_NO_EMPTY);
注意: - 逗号分隔列表由用户使用textarea提供。
答案 0 :(得分:2)
我总是试图指出解决方案的正确性始终优先于它的工作速度。一些不起作用但速度非常快的东西就像一个有效的东西一样,但是真的很慢。
因此,我将分别解决解决方案的正确性和效率。
explode()
和trim()
与array_map()
的组合,可以很好地实现您期望的目标。
$cityNamesArray = array_map('trim', explode(',', $cityNames ));
您也可以在此处输入array_filter()
以确保零长度字符串不会通过。所以在像"Chicago, San Diego, El Paso,, New York,"
这样的字符串中,你不会得到一个带有一些空值的数组。
$cityNamesArray = array_filter(array_map('trim', explode(',', $cityNames )), 'strlen');
这假设数据可能不一致,并且中断对所需的最终结果产生不利影响。所以解决方案的正确性与此有关。
此处函数调用的组合会导致数组多次迭代,因此您有O(n * 2 + k)
时间,其中k
是字符串中要查找定界的数字字符,而n
是生成的数组中的元素数量通过array_map
和array_filter
。
现在考虑如何让它更快,我们需要让大O更接近O(k)
以获得最佳解决方案,因为你无法通过单个字符进一步减少k
needle / haystack substring search。
preg_split('/\s*,\s*/', $cityNames, -1, PREG_SPLIT_NO_EMPTY)
方法的时间复杂度约为O(k)
,因为如果PCRE VM中有多次传递,则不大于O(k + 1)
或最差情况O(k + log k)
。
它也适用于$cityNames = "Chicago, San Diego, El Paso,, New York,"
或类似结果的上述情况。
这意味着它符合正确性和效率的标准。因此,我认为这是最佳解决方案。
话虽如此,我认为你会发现两种方法之间的性能差异可以忽略不计。
这是一个基本的基准,以证明差异对平均投入的影响微不足道。
$cityNames = "Chicago, San Diego,El Paso,,New York, ,"; // sample data
$T = 0; // total time spent
for($n = 0; $n < 10000; $n++) {
$t = microtime(true); // start time
preg_split('/\s*,\s*/', $cityNames, -1, PREG_SPLIT_NO_EMPTY);
$t = microtime(true) - $t; // end time
$T += $t; // aggregate time
}
printf("preg_split took %.06f seconds on average", $T / $n);
$T = 0; // total time spent
for($n = 0; $n < 10000; $n++) {
$t = microtime(true); // start time
array_filter(array_map('trim', explode(',', $cityNames )), 'strlen');
$t = microtime(true) - $t; // end time
$T += $t; // aggregate time
}
printf("array functions took %.06f seconds on average", $T / $n);
preg_split took 0.000003 seconds on average array functions took 0.000005 seconds on average
这是它们之间的平均差异,可能是1或2微秒。当测量这种微小的速度差异时,只要解决方案产生正确性,你就不应该太在意。解决性能问题的更好方法是按数量级进行测量。一个快1或2微秒的解决方案不值得探索,如果它花费更多的时间,而不仅仅是使用几乎的现有解决方案,但同样正确。但是,可能会快速提高1或2个数量级的解决方案。
答案 1 :(得分:1)
提示如果您不需要正则表达式的强大功能,您可以选择 更快(尽管更简单)的替代方案,如explode()或str_split()。
关于准确性,在这两种情况下都会出现问题,如在给定的示例中,您将拥有以下数组:
[1] => "Chicago"
[2] => " San Diego"
[3] => " El Paso"
(注意[2]和[3]中的额外空间)
解决这个问题的一种方法是替换所有出现的&#34;,&#34;到&#34;,&#34;像这样:
$cityNames = str_replace(', ', ',', $cityNames);
编辑:(失眠让我变得更好)
请确保在分隔符中包含空格:
$cityNamesArray = explode(", ", $cityNames);
答案 2 :(得分:0)
在一个简单的用法中,explode()要快一些,请参阅:http://micro-optimization.com/explode-vs-preg_split
但是preg_split的优点是支持标签(\ t)和空格用\ s。
\ s元字符用于查找空白字符。
空格字符可以是(http://php.net/manual/en/regexp.reference.escape.php):
空格字符(32 = 0x20)
制表符(9 = 0x09)
回车符(13 = 0x0D)
新行字符(10 = 0x0A)
换页符(12 = 0x0C)
在这种情况下,您应该看到成本和收益。
提示,使用array_filter“删除”数组中的空项:
示例:
$ keyword = explore('',$ _GET ['search']); //或preg_split 的print_r($关键字);
$ keyword = array_filter($ arr,'empty'); 的print_r($关键字);