Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP - sort hash array by key length

I've found a few answers to sorting by value, but not key.

What I'd like to do is a reverse sort, so with:

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

I'd like them to be in this order

  1. reallylongname
  2. mediumname
  3. shortname

mediumname shortname

Many thanks

like image 534
Grant Avatar asked Oct 17 '10 22:10

Grant


4 Answers

Another solution using array_multisort:

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

Here $keys is an array of the lengths of the keys of $arr. That array is sorted in descending order and then used to sort the values of $arr using array_multisort.

like image 79
Gumbo Avatar answered Nov 10 '22 03:11

Gumbo


I have benchmarked some of sorting algorithms since performance is important for my project - here's what I've found (averaged result ran 1000x, sorted field had cca 300 elements with key size 3-50 chars):

  • 2.01 sec ... uksort with anonymous create_function (by cojam)
  • 0.28 sec ... array_multisort (by Gumbo)
  • 2.69 sec ... uksort with non-anonymous function (by Colin Herbert) - surprise for me,
  • 0.15 sec ... simple foreach + arsort

Sometime simple foreach still wins. Using dynamic PHP features has some performance penalty, obviously.

like image 32
lubosdz Avatar answered Sep 16 '22 21:09

lubosdz


Based on @thetaiko answer, with a simpler callback :

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

uksort($nametocode, "sortByLengthReverse");

Resources :

  • php.net - uksort()
  • php.net - Sorting arrays
  • php.net - strlen()
like image 10
Colin Hebert Avatar answered Nov 10 '22 03:11

Colin Hebert


You can use a user defined key sort function as a callback for 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";
}

Quick note - to reverse the sort simply switch "1" and "-1".

like image 9
thetaiko Avatar answered Nov 10 '22 04:11

thetaiko