harry
harry

Reputation:

Sorting an array of arrays by the child array's length?

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

Upvotes: 2

Views: 1617

Answers (4)

mickmackusa
mickmackusa

Reputation: 47903

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

Upvotes: 0

kyle
kyle

Reputation: 1470

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

Upvotes: 0

David Z
David Z

Reputation: 131600

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

Upvotes: 3

too much php
too much php

Reputation: 91028

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().

Upvotes: 4

Related Questions