2

What's the best way in PHP to sort an array of arrays based on array length?

e.g.

$parent[0] = array(0, 0, 0);
$parent[2] = array("foo", "bar", "b", "a", "z");
$parent[1] = array(4, 2);

$sorted = sort_by_length($parent)

$sorted[0] = array(4, 2);
$sorted[1] = array(0, 0, 0);
$sorted[2] = array("foo", "bar", "b", "a", "z");

4 Answers 4

4

This will work:

function sort_by_length($arrays) {
    $lengths = array_map('count', $arrays);
    asort($lengths);
    $return = array();
    foreach(array_keys($lengths) as $k)
        $return[$k] = $arrays[$k];
    return $return;
}

Note that this function will preserve the numerical keys. If you want to reset the keys, wrap it in a call to array_values().

Sign up to request clarification or add additional context in comments.

Comments

3

I'm upvoting Peter's but here's another way, I think:

function cmp($a1, $a2) {
    if (count($a1) == count($a2)) {
        return 0;
    }
    return (count($a1) < count($a2)) ? -1 : 1;
}

usort($array, "cmp");

2 Comments

This worked but did not maintain the keys. Thanks for the answer.
I was able to preserve the keys by using uasort instead of usort.
0

Try the usort function:

function sortByLength( $arr1, $arr2 )
{
    $c1 = count($arr1);
    $c2 = count($arr2);

    return $c1 < $c2 ? -1 : $c1 == $c2 ? 0 : 1;
}

usort($initial_array,'sortByLength');

edited to respect parameters-by-reference; it's the same answer as @david, anyway

Comments

0

sort() compares by size before quality.

Because all of your rows have the same flat structure, sort() will sort ascending by row size, sort ascending by first elements, then the next elements, etc.

Code: (Demo)

$parent[0] = array(0, 0, 0);
$parent[2] = array("foo", "bar", "b", "a", "z");
$parent[1] = array(4, 2);
$parent[5] = array(11, 2);
$parent[3] = array(1, 21);
$parent[4] = array(11, 1);

sort($parent);
var_export($parent);

Output:

array (
  0 => 
  array (
    0 => 1,
    1 => 21,
  ),
  1 => 
  array (
    0 => 4,
    1 => 2,
  ),
  2 => 
  array (
    0 => 11,
    1 => 1,
  ),
  3 => 
  array (
    0 => 11,
    1 => 2,
  ),
  4 => 
  array (
    0 => 0,
    1 => 0,
    2 => 0,
  ),
  5 => 
  array (
    0 => 'foo',
    1 => 'bar',
    2 => 'b',
    3 => 'a',
    4 => 'z',
  ),
)

This performs identically to this use of array_multisort() with iterated calls of count: (Demo)

array_multisort(array_map('count', $parent), $parent);
var_export($parent);

Using usort() is different if only sorting on the counts because in modern PHP it will leave tied comparisons in their original position : (Demo)

usort($parent, fn($a, $b) => count($a) <=> count($b));
var_export($parent);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.