46

I have an array like the following:

Array
(
    [0] => Array
        (
            'name' => "Friday"
            'weight' => 6
        )
    [1] => Array
        (
            'name' => "Monday"
            'weight' => 2
        )
)

I would like to grab the last values in that array (the 'weight'), and use that to sort the main array elements. So, in this array, I'd want to sort it so the 'Monday' element appears before the 'Friday' element.

codaddict
  • 445,704
  • 82
  • 492
  • 529
geerlingguy
  • 4,682
  • 8
  • 56
  • 92
  • Yes, this looks to be the case. I looked at that issue before this, but didn't quite understand it until reading through the replies to this thread... ah well :( – geerlingguy Sep 24 '10 at 18:31

7 Answers7

47

You can use usort as:

function cmp($a, $b) {
   return $a['weight'] - $b['weight'];
}

usort($arr,"cmp");
codaddict
  • 445,704
  • 82
  • 492
  • 529
9

Can be done using an anonymous function.

Also if your 'weight' is a string use one of the other returns (see the commented out lines):

<?php

$arr = array(
    0 => array (
        'name'   => 'Friday',
        'weight' => 6,
    ),
    1 => array (
        'name'   => 'Monday',
        'weight' => 2,
    ),
);

// sort by 'weight'
usort($arr, function($a, $b) { // anonymous function
    // compare numbers only
    return $a['weight'] - $b['weight'];

    // compare numbers or strings
    //return strcmp($a['weight'], $b['weight']);

    // compare numbers or strings non-case-sensitive
    //return strcmp(strtoupper($a['weight']), strtoupper($b['weight']));
});

var_export($arr);

/*
array (
    0 => array (
        'name'   => 'Monday',
        'weight' => 2,
    ),
    1 => array (
        'name'   => 'Friday',
        'weight' => 6,
    ),
)
*/
Geo
  • 12,666
  • 4
  • 40
  • 55
9

You can also use an anonymous function.

usort($items, function($a, $b) {
    return $a['name'] > $b['name'];
});
Richard Ayotte
  • 5,021
  • 1
  • 36
  • 34
3

Agree with usort, I also sometimes use array_multisort (http://ca2.php.net/manual/en/function.usort.php) example 3, sorting database results. You could do something like:

<?php
$days = array(
  array('name' => 'Friday', 'weight' => 6),
  array('name' => 'Monday', 'weight' => 2),
);

$weight = array();
foreach($days as $k => $d) {
  $weight[$k] = $d['weight'];
}

print_r($days);

array_multisort($weight, SORT_ASC, $days);

print_r($days);
?>

Output:

Array
(
    [0] => Array
        (
            [name] => Friday
            [weight] => 6
        )

    [1] => Array
        (
            [name] => Monday
            [weight] => 2
        )

)
Array
(
    [0] => Array
        (
            [name] => Monday
            [weight] => 2
        )

    [1] => Array
        (
            [name] => Friday
            [weight] => 6
        )

)
2

If the filed you sort by is string like title name,
array_multisort + Flags for Natural Sorting and CaseInSensitivity are the way to go:

$sort_by_title = array();
foreach($items as $item) {
  $sort_by_title [] = $item['title'];
}
array_multisort($sort_by_title , SORT_ASC, SORT_NATURAL | SORT_FLAG_CASE, $items );
d.raev
  • 9,216
  • 8
  • 58
  • 79
0

NOTE, if the element you are sorting on is a float like .0534 and .0353 (like for a percentage), then you have to multiply both by 1000. not sure why frankly... it appears that usort seems to compare the integer values.

took me awhile to figure that one out...

and 2 tips that may not be immediately obvious:

  1. if your arrays are objects, you can use return $a->weight - $b->weight of course
  2. if you return $b->weight - $a->weight, it will sort desending.
Barry
  • 116
  • 3
-1

Here's a cool function that might help:

function subval_sort($a,$subkey,$sort) {
    foreach($a as $k=>$v) {
        $b[$k] = strtolower($v[$subkey]);
    }
    if($b)
    {
        $sort($b);
        foreach($b as $key=>$val) {
            $c[] = $a[$key];
        }
        return $c;
    }
}

Send in the array as $a the key as $subkey and 'asort' or 'sort' for the $sort variable

d2burke
  • 4,081
  • 3
  • 39
  • 51