Определить наиболее распространенное расширение в массиве - PullRequest
2 голосов
/ 02 мая 2011

Примите во внимание следующий код:

$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() не пуленепробиваемый ... Есть идеи?

Ответы [ 2 ]

0 голосов
/ 03 мая 2011

Я долго думал над этим вопросом, и я думаю, что ваш первый фрагмент в значительной степени является ответом на него.Это не так, как короткий код, это более быстрый код.Этот код довольно быстрый и линейно масштабируется до больших массивов.Это в значительной степени сложность O (n) плюс алгоритм сортировки arsort (я понятия не имею, какой метод он использует, но я ожидаю, что он будет быстрее, чем самостоятельно написанный).Единственное, что я могу предложить, - это маленькая функция, содержащая ваши фрагменты и небольшая подстройка в случае, если расширение отсутствует в массиве.

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;
}

Я не знаю, сколько элементов в ваших массивах и какваш вариант использования критичен по времени, но этот метод будет успешным.

0 голосов
/ 02 мая 2011

Я бы сделал что-то вроде этого:

<?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));
?>

Это вернет массив, где значения будут общими расширениями, даже если их много.

Примечание: не используйте regex, когда ваша работа может выполнять основные функции PHP - регулярное выражение слишком ресурсоемко по сравнению со встроенными функциями php.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...