sort array by sub arrray values?

Discussion in 'PHP' started by mikemotorcade, Feb 14, 2008.

  1. #1
    I'm trying to figure out the best way to sort an array. This is what the array looks like:

    Array
    (
        [11687] => Array
            (
                [passed] => 2
                [failed] => 4
            )
    
        [8545] => Array
            (
                [passed] => 1
                [failed] => 0
            )
    
        [1631] => Array
            (
                [passed] => 12
                [failed] => 16
            )
    
        [2251] => Array
            (
                [passed] => 1
                [failed] => 1
            )
    )
    PHP:
    I'm trying to sort it by the sum of passed and failed. So the order would end up like this: 1631,11687,2251,8545.

    Any ideas?
     
    mikemotorcade, Feb 14, 2008 IP
  2. nico_swd

    nico_swd Prominent Member

    Messages:
    4,153
    Likes Received:
    344
    Best Answers:
    18
    Trophy Points:
    375
    #2
    Loop over the values, and create 2 (or 3, if necessary) arrays. One array holding all "passed" values, and one holding all "failed" values.

    Then use array_multisort() and you're done.
     
    nico_swd, Feb 14, 2008 IP
  3. stoli

    stoli Peon

    Messages:
    69
    Likes Received:
    14
    Best Answers:
    0
    Trophy Points:
    0
    #3
    You could use usort() and define a custom sorting function. The only trouble with that is it assigns new array keys. That isn't really a problem if you run it on a copy of your array though.

    Here is how that would look:
    <?php
    
    $test = Array
    (
        11687 => Array
            (
                'passed' => 2,
                'failed' => 4
            ),
    
        8545 => Array
            (
                'passed' => 1,
                'failed' => 0
            ),
    
        1631 => Array
            (
                'passed' => 12,
                'failed' => 16
            ),
    
        2251 => Array
            (
                'passed' => 1,
                'failed' => 1
            )
    );
    
    // Add another key (alongside 'passed' and 'failed') to save the key numbers - usort assigns new keys, removing any existing ones
    while (list($key, $value) = each($test)) {
      $test[$key]['key'] = $key;
    }
    
    echo "Before...<br>\n";
    reset($test);
    while (list($key, $value) = each($test)) {
        echo "$key ";
    }
    
    usort($test, "cmp");
    
    reset($test);
    echo "<br>After...<br>\n";
    while (list($key, $value) = each($test)) {
        echo $test[$key]['key']." ";
    }
    
    function cmp($a, $b) {
        if (($a['passed']+$a['failed']) == ($b['passed']+$b['failed'])) {
            return 0;
        }
        return (($a['passed']+$a['failed']) > $b['passed']+$b['failed']) ? -1 : 1;
    }
    
    ?>
    PHP:
     
    stoli, Feb 14, 2008 IP
  4. zerxer

    zerxer Peon

    Messages:
    368
    Likes Received:
    18
    Best Answers:
    0
    Trophy Points:
    0
    #4
    Actually, you can use UASORT instead of USORT and eliminate all that process of having to store the keys and reassign them.

    I've also made the compare function shorter, and I stored it in a variable using the create_function() method since it's really only a disposable function that you're only going to need to sort the array so no point in having a full function for it.

    <?php
    
    $test = Array
    (
        11687 => Array
            (
                'passed' => 2,
                'failed' => 4
            ),
    
        8545 => Array
            (
                'passed' => 1,
                'failed' => 0
            ),
    
        1631 => Array
            (
                'passed' => 12,
                'failed' => 16
            ),
    
        2251 => Array
            (
                'passed' => 1,
                'failed' => 1
            )
    );
    
    print "Unsorted:<br />";
    
    print_r($test);
    
    $sort_function = create_function('$a,$b', 'return ($b[\'passed\'] + $b[\'failed\']) - ($a[\'passed\'] + $a[\'failed\']);');
    uasort($test, $sort_function);
    
    print "<br />Sorted:<br />";
    print_r($test);
    
    ?>
    PHP:
     
    zerxer, Feb 15, 2008 IP
  5. stoli

    stoli Peon

    Messages:
    69
    Likes Received:
    14
    Best Answers:
    0
    Trophy Points:
    0
    #5
    Indeed, much neater. Nice work zerxer.
     
    stoli, Feb 15, 2008 IP
  6. mikemotorcade

    mikemotorcade Peon

    Messages:
    645
    Likes Received:
    49
    Best Answers:
    0
    Trophy Points:
    0
    #6
    Thanks, works great!
     
    mikemotorcade, Feb 15, 2008 IP