2011-05-02 59 views
2

看看下面的代碼考慮:找出最常見的擴展在Array

$files = array('1.js', '1.css', '2.js', '2.css', '3.js', '3.png'); 
$extensions = array(); 

foreach ($files as $file) 
{ 
    $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION)); 

    if (empty($extensions[$extension]) === true) 
    { 
     $extensions[$extension] = 0; 
    } 

    ++$extensions[$extension]; 
} 

arsort($extensions); // array('js' => 3, 'css' => 2, 'png' => 1) 

$common_extension = key($extensions); // js 

的代碼似乎工作,因爲我希望它(我仍然需要檢查發生了什麼萬一有一場平局,但這與這個問題無關)。我在尋找一種更有效的(和緊湊的方式)重寫上面的代碼中的,到目前爲止,我已經得到了最接近的是:

$files = array('1.js', '1.css', '2.js', '2.css', '3.js', '3.png'); 
$extensions = array_count_values(array_map('strtolower', preg_replace('~^.*[.](.*)$~', '$1', $files))); 

arsort($extensions, SORT_NUMERIC); 

$common_extension = key($extensions); 

但這遍歷數組的3倍,並且preg_replace()不是防彈... 有任何想法嗎?

+0

我會使用普通的字符串函數,而不是正則表達式,如果你關心它。缺點是你最終會多出幾行,因爲你不能將數組傳遞給這些字符串函數。 – 2011-05-02 01:35:59

+1

您可以編寫自己的方法,其中包含'strtolower'和''pathinfo'片段以用於'array_map'調用。這將爲您節省一次迭代。如果你不想'array_count_values'再次運行數組,你必須再次指望你自己。 – Frank 2011-05-02 01:47:37

回答

0

我會做這樣的事情:

<?php 
function getCommon($array, $result = array()) { 
    foreach ($array as $k => $v) { $array[$k] = strtolower(pathinfo($v, PATHINFO_EXTENSION)); } 
    $ext = array_count_values($array); arsort($ext,SORT_NUMERIC); 
    $k = array_keys($ext); $k0 = $k[0]; 
    if ($ext[$k0] > $ext[$k[1]]) { $result[] = $k0; } 
    else { foreach ($ext as $k => $v) { if ($v == $ext[$k0]) { $result[] = $k; } } } 
    return $result; 
} 

$files = array('1.js', '2.js', '3.png', '4.css'); 
print_R($files); 
print_R(getCommon($files)); 

$files2 = array('1.js', '2.js', '3.png', '4.png', '5.css'); 
print_R($files2); 
print_R(getCommon($files2)); 
?> 

這將返回一個數組,其中值是常用的擴展,即使他們有很多。

注意:當您的工作基本PHP功能可以完成時,請勿使用正則表達式 - 與php內置函數相比,regex太耗費資源。

+0

這似乎是做了我的第一個片段,但你正在循環陣列4次,我沒有得到改善。 – 2011-05-02 13:14:31

+0

它也返回draws,它不使用正則表達式,它更短。 – Deele 2011-05-02 13:18:19

0

我已經考慮過這個問題很長一段時間了,我認爲你的第一個片段幾乎是它的答案。它不像更短的代碼是更快的代碼。該代碼速度非常快,可以線性擴展到更大的陣列。這幾乎是O(n)的複雜度加上排序算法0​​(我不知道它使用的是什麼方法,但我希望它比自己寫的更快)。我可以提供的唯一的事情是這個包含你的片段的小函數,並且在擴展不在數組中的情況下做一些調整。

function count_ext($array){ 
    $ret = array(); 
    foreach($array as $ext){ 
     $ext = strtolower(pathinfo($ext, PATHINFO_EXTENSION)); 
     if(!isset($ret[$ext])) $ret[$ext] = 0; 
     $ret[$ext]++; 
    } 
    arsort($ret); 
    return $ret; 
} 

我不知道你的數組有多少元素以及你的用例對時間有多重要,但是這種方法會很好。