2016-09-09 130 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

相關問題