PHP - сортировать хеш-массив по длине ключа - PullRequest
12 голосов
/ 18 октября 2010

Я нашел несколько ответов на сортировку по значению, но не по ключу.

Я хотел бы сделать обратную сортировку, поэтому с:

    $nametocode['reallylongname']='12';
    $nametocode['shortname']='10';
    $nametocode['mediumname']='11';

Iхотелось бы, чтобы они были в таком порядке

  1. действительно длинное имя
  2. имя_среды
  3. имя_символа

имя_символа

Большое спасибо

Ответы [ 11 ]

23 голосов
/ 18 октября 2010

Другое решение с использованием array_multisort:

$keys = array_map('strlen', array_keys($arr));
array_multisort($keys, SORT_DESC, $arr);

Здесь $keys - это массив длин клавиш $arr. Этот массив сортируется в порядке убывания, а затем используется для сортировки значений $arr с использованием array_multisort.

8 голосов
/ 18 октября 2010

На основе ответа @thetaiko с более простым обратным вызовом:

function sortByLengthReverse($a, $b){
    return strlen($b) - strlen($a);
}

uksort($nametocode, "sortByLengthReverse");

Ресурсы:

8 голосов
/ 18 октября 2010

Вы можете использовать пользовательскую функцию сортировки ключей в качестве обратного вызова для uksort:

function cmp($a, $b)
{
    if (strlen($a) == strlen($b))
        return 0;
    if (strlen($a) > strlen($b))
        return 1;
    return -1;
}

uksort($nametocode, "cmp");

foreach ($nametocode as $key => $value) {
    echo "$key: $value\n";
}

Быстрое примечание - чтобы изменить сортировку, просто переключите "1" и "-1".

4 голосов
/ 01 ноября 2011

Вот мои мощные встроенные методологии. Сохраняйте глобальное пространство для будущих поколений!

uksort($data, create_function('$a,$b', 'return strlen($a) < strlen($b);'));
2 голосов
/ 02 января 2015

Одним из ограничений при сортировке ключей по длине является то, что ключи одинаковой длины не переупорядочиваются. Скажем, нам нужно заказать ключи по длине в порядке descending.

<code>$arr = array(
    "foo 0" => "apple",
    "foo 1" => "ball",
    "foo 2 foo 0 foo 0" => "cat",
    "foo 2 foo 0 foo 1 foo 0" => "dog",
    "foo 2 foo 0 foo 1 foo 1" => "elephant",
    "foo 2 foo 1 foo 0" => "fish",
    "foo 2 foo 1 foo 1" => "giraffe"
);

debug($arr, "before sort");
$arrBad = $arr;
sortKeysDescBAD($arrBad);
debug($arrBad, "after BAD sort");
sortKeysDescGOOD($arr);
debug($arr, "after GOOD sort 2");

function sortKeysDescBAD(&$arrNew) {
    $arrKeysLength = array_map('strlen', array_keys($arrNew));
    array_multisort($arrKeysLength, SORT_DESC, $arrNew);
    //return max($arrKeysLength);
}

function sortKeysDescGOOD(&$arrNew) {
    uksort($arrNew, function($a, $b) {
        $lenA = strlen($a); $lenB = strlen($b);
        if($lenA == $lenB) {
            // If equal length, sort again by descending
            $arrOrig = array($a, $b);
            $arrSort = $arrOrig;
            rsort($arrSort);
            if($arrOrig[0] !== $arrSort[0]) return 1;
        } else {
            // If not equal length, simple
            return $lenB - $lenA;
        }
    });
}

function debug($arr, $title = "") {
    if($title !== "") echo "<br/><strong>{$title}</strong><br/>";
    echo "<pre>"; print_r($arr); echo "
<ч /> "; }

Вывод будет:

before sort
Array
(
    [foo 0] => apple
    [foo 1] => ball
    [foo 2 foo 0 foo 0] => cat
    [foo 2 foo 0 foo 1 foo 0] => dog
    [foo 2 foo 0 foo 1 foo 1] => elephant
    [foo 2 foo 1 foo 0] => fish
    [foo 2 foo 1 foo 1] => giraffe
)

after BAD sort
Array
(
    [foo 2 foo 0 foo 1 foo 0] => dog
    [foo 2 foo 0 foo 1 foo 1] => elephant
    [foo 2 foo 0 foo 0] => cat
    [foo 2 foo 1 foo 0] => fish
    [foo 2 foo 1 foo 1] => giraffe
    [foo 0] => apple
    [foo 1] => ball
)

after GOOD sort
Array
(
    [foo 2 foo 0 foo 1 foo 1] => elephant
    [foo 2 foo 0 foo 1 foo 0] => dog
    [foo 2 foo 1 foo 1] => giraffe
    [foo 2 foo 1 foo 0] => fish
    [foo 2 foo 0 foo 0] => cat
    [foo 1] => ball
    [foo 0] => apple
)

Обратите внимание на порядок elephant и dog, например (или другие) в двух методах сортировки. Второй способ выглядит лучше. Возможно, есть более простые способы решить эту проблему, но надеюсь, что это кому-то поможет ...

2 голосов
/ 08 января 2014

Я протестировал некоторые алгоритмы сортировки, так как производительность важна для моего проекта - вот что я нашел (усредненный результат побежал 1000x, в отсортированном поле было около 300 элементов с размером ключа 3-50 символов):

  • 2,01 сек ... uksort с анонимной функцией create_ (by cojam)
  • 0.28 сек ... array_multisort (by Gumbo)
  • 2.69 сек ... uksort с неанонимной функцией(Колин Герберт) - сюрприз для меня,
  • 0,15 сек ... простой foreach + арсорт

Иногда простой foreach все еще выигрывает.Очевидно, что использование динамических функций PHP имеет некоторое снижение производительности.

1 голос
/ 10 мая 2018

В PHP7 + вы можете использовать uksort() с оператором космического корабля и анонимной функцией, например:

uksort($array, function($a, $b) {
    return strlen($b) <=> strlen($a);
});
1 голос
/ 18 октября 2010

Взгляните на уксорт .

0 голосов
/ 04 июля 2018

Для абсолютного использования uksort вы можете сделать так:

$nametocode['reallylongname']='12';
$nametocode['name']='17';
$nametocode['shortname']='10';
$nametocode['mediumname']='11';

uksort($nametocode, function($a, $b) {
   return strlen($a) - strlen($b);
});

array_reverse($nametocode, true);

Вывод:

Array
(
   [reallylongname] => 12
   [mediumname] => 11
   [shortname] => 10
   [name] => 17
)

Я тестировал этот код.

0 голосов
/ 03 марта 2017

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

uksort($yourArray, function ($a, $b) { 
   return (strlen($a) == strlen($b) ? strcmp($a, $b) : strlen($a) - strlen($b));
});

Этот код выполняетто же самое в обратном порядке:

uksort($yourArray, function ($b, $a) { 
   return (strlen($a) == strlen($b) ? strcmp($a, $b) : strlen($a) - strlen($b));
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...