2016-09-09 105 views
0

我用逗号分隔的城市名称列表。 ($ cityNames可能含有100至500名)将逗号分隔列表转换为数组 - 爆炸vs preg_split

$cityNames = "Chicago, San Diego, El Paso"; 

以下哪一个是更好的逗号分隔的列表转换成数组,牢记性能和精度?

$cityNamesArray = explode(",", $cityNames); 

$cityNamesArray = preg_split('/\s*,\s*/', $cityNames, -1, PREG_SPLIT_NO_EMPTY); 

注: - 昏迷分隔的列表由用户提供,使用文本区域。

+0

如果你经常这样做,最好只创建一次数组。然后存储数组varraible而不是字符串 – nogad

+0

在我的情况下,昏迷分隔列表是由用户使用textarea提供的。 – Syed

+0

奇怪的用户输入,但你可能应该考虑他们可能会把它弄乱了额外的空间或(任何) – nogad

回答

2

我总是喜欢尝试和点认为解决方案的正确性总是优先于其工作速度。某些不起作用但速度很快的问题与某些可行的问题一样多,但速度很慢。

所以我将分别解决解决方案的正确性和效率问题。

正确性

结合array_map()explode()trim()相结合,很好地工作在这里实现自己的预期目标。

$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任何进一步/干草堆子串搜索。

preg_split('/\s*,\s*/', $cityNames, -1, PREG_SPLIT_NO_EMPTY)方法具有约O(k)时间复杂度,因为它是不太可能超过O(k + 1)或最坏的情况下,如果O(k + log k)比在PCRE VM单次多。

它也适用于上述情况,其中$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个数量级的解决方案可能是。

+0

矫枉过正:P完成! – theomessin

1

According to PHP.NET

提示如果不需要正则表达式的能力,你可以选择 更快(虽然简单)的替代品像爆炸()或str_split()。


关于准确性,你将有一个问题,在这两种情况下,如你给出的例子中,你将有以下阵列:

[1] => "Chicago" 
[2] => " San Diego" 
[3] => " El Paso" 

(请注意额外的空间[2]和[3])

的一种方法来解决,这将是取代的所有出现“‘到’,”像这样:

$cityNames = str_replace(', ', ',', $cityNames); 

编辑:(失眠了我的更好)

只需确保在您的分隔符的空间:

$cityNamesArray = explode(", ", $cityNames); 
+1

你可以爆炸“,”不只是逗号 – nogad

+0

这也会工作:P Jeez,我得让我睡一觉。 – theomessin

+1

该方法的问题在于如果提供的字符串是“芝加哥,圣地亚哥,埃尔帕索”,请注意该问题表明字符串是用户提供的数据,这意味着您不能相信用户将正确包含每个城市之间的空间偶然或故意。 – Sherif

0

在一个简单的用法爆炸()是速度比,请参见:http://micro-optimization.com/explode-vs-preg_split

但使preg_split具有支撑片(\ t)和与\ S空间的优点。

\的元字符用于查找空白字符。

空白字符可以是(http://php.net/manual/en/regexp.reference.escape.php):

  • 空格字符(32 = 0×20)

  • 制表符(9 = 0×09)

  • 回车符(13 = 0x0D)

  • 新行字符(10 = 0x0A)

  • 换页符(12 = 0x0C)

在这种情况下,应该看到的成本和益处。

尖端,使用array_filter在数组 “删除” 空项:

实施例:

$关键字=探索(””,$ _GET [ '搜索']); //或preg_split print_r($ keyword);

$ keyword = array_filter($ arr,'empty'); print_r($ keyword);

注意:RegExp Perfomance

相关问题