How to sort an array of associative arrays by value of a given key in PHP?

Viewed 680770

Given this array:

$inventory = array(

   array("type"=>"fruit", "price"=>3.50),
   array("type"=>"milk", "price"=>2.90),
   array("type"=>"pork", "price"=>5.43),

);

I would like to sort $inventory's elements by price to get:

$inventory = array(

   array("type"=>"pork", "price"=>5.43),
   array("type"=>"fruit", "price"=>3.50),
   array("type"=>"milk", "price"=>2.90),

);

How can I do this?

23 Answers

For PHP 7 and later versions.

/**
 * A method for sorting associative arrays by a key and a direction.
 * Direction can be ASC or DESC.
 *
 * @param $array
 * @param $key
 * @param $direction
 * @return mixed $array
 */
function sortAssociativeArrayByKey($array, $key, $direction){

    switch ($direction){
        case "ASC":
            usort($array, function ($first, $second) use ($key) {
                return $first[$key] <=> $second[$key];
            });
            break;
        case "DESC":
            usort($array, function ($first, $second) use ($key) {
                return $second[$key] <=> $first[$key];
            });
            break;
        default:
            break;
    }

    return $array;
}

Usage:

$inventory = sortAssociativeArrayByKey($inventory, "price", "ASC");

I use uasort like this

<?php
$users = [
    [
        'username' => 'joe',
        'age' => 11
    ],
    [
        'username' => 'rakoto',
        'age' => 21
    ],
    [
        'username' => 'rabe',
        'age' => 17
    ],
    [
        'username' => 'fy',
        'age' => 19
    ],    
];


uasort($users, function ($item, $compare) {
    return $item['username'] >= $compare['username']; 
});

var_dump($users);

try this:

$prices = array_column($inventory, 'price');
array_multisort($prices, SORT_DESC, $inventory);
print_r($inventory);

As of PHP 7.4, you can use arrow function:

usort(
    $inventory, 
    fn(array $a, array $b): int => $b['price'] <=> $a['price']
);

Code (demo):

$inventory = [
    ['type' => 'fruit', 'price' => 3.50],
    ['type' => 'milk',  'price' => 2.90],
    ['type' => 'pork',  'price' => 5.43],
];

usort(
    $inventory, 
    fn(array $a, array $b): int => $b['price'] <=> $a['price']
);

print_r($inventory);

(condensed) Output:

Array
(
    [0] => Array ([type] => pork,  [price] => 5.43)
    [1] => Array ([type] => fruit, [price] => 3.5)
    [2] => Array ([type] => milk,  [price] => 2.9)
)

Here is a method that I found long ago and cleaned up a bit. This works great, and can be quickly changed to accept objects as well.

/**
 * A method for sorting arrays by a certain key:value.
 * SortByKey is the key you wish to sort by
 * Direction can be ASC or DESC.
 *
 * @param $array
 * @param $sortByKey
 * @param $sortDirection
 * @return array
 */
private function sortArray($array, $sortByKey, $sortDirection) {

    $sortArray = array();
    $tempArray = array();

    foreach ( $array as $key => $value ) {
        $tempArray[] = strtolower( $value[ $sortByKey ] );
    }

    if($sortDirection=='ASC'){ asort($tempArray ); }
        else{ arsort($tempArray ); }

    foreach ( $tempArray as $key => $temp ){
        $sortArray[] = $array[ $key ];
    }

    return $sortArray;

}

to change the method to sort objects simply change the following line:

$tempArray[] = strtolower( $value[ $sortByKey ] ); to $tempArray[] = strtolower( $value->$sortByKey );

To run the method simply do

sortArray($inventory,'price','ASC');

Complete Dynamic Function I jumped here for associative array sorting and found this amazing function on http://php.net/manual/en/function.sort.php. This function is very dynamic that sort in ascending and descending order with specified key.

Simple function to sort an array by a specific key. Maintains index association

<?php

function array_sort($array, $on, $order=SORT_ASC)
{
    $new_array = array();
    $sortable_array = array();

    if (count($array) > 0) {
        foreach ($array as $k => $v) {
            if (is_array($v)) {
                foreach ($v as $k2 => $v2) {
                    if ($k2 == $on) {
                        $sortable_array[$k] = $v2;
                    }
                }
            } else {
                $sortable_array[$k] = $v;
            }
        }

        switch ($order) {
            case SORT_ASC:
                asort($sortable_array);
            break;
            case SORT_DESC:
                arsort($sortable_array);
            break;
        }

        foreach ($sortable_array as $k => $v) {
            $new_array[$k] = $array[$k];
        }
    }

    return $new_array;
}

$people = array(
    12345 => array(
        'id' => 12345,
        'first_name' => 'Joe',
        'surname' => 'Bloggs',
        'age' => 23,
        'sex' => 'm'
    ),
    12346 => array(
        'id' => 12346,
        'first_name' => 'Adam',
        'surname' => 'Smith',
        'age' => 18,
        'sex' => 'm'
    ),
    12347 => array(
        'id' => 12347,
        'first_name' => 'Amy',
        'surname' => 'Jones',
        'age' => 21,
        'sex' => 'f'
    )
);

print_r(array_sort($people, 'age', SORT_DESC)); // Sort by oldest first
print_r(array_sort($people, 'surname', SORT_ASC)); // Sort by surname

If you need to sort an array of strings with different cases, this will change the sorting array values to lowercase.

$data = [
    [
        'name' => 'jack',
        'eyeColor' => 'green'
    ],
    [
        'name' => 'Amy',
        'eyeColor' => 'brown'
    ],
    [   
        'name' => 'Cody',
        'eyeColor' => 'blue'
    ] 
];
function toLowerCase($a) { return strtolower($a); }
$sortArray = array_map("toLowerCase",array_column($data, 'name'));
array_multisort($sortArray, SORT_ASC, $data);

This function works 100% on all major versions of PHP and it is tested with PHP5, PHP7, PHP8.

    function sort_my_array($array, $order_by, $order)
    {
        switch ($order) {
            case "asc":
                usort($array, function ($first, $second) use ($order_by) {
                    if (version_compare(PHP_VERSION, '7.0.0') >= 0) {
                        return $first[$order_by] <=> $second[$order_by];
                    } else {
                        $array_cmp = strcmp($first[$order_by], $second[$order_by]);
                        return $array_cmp ;
                    }
                });
                break;
            case "desc":
                usort($certificates, function ($first, $second) use ($order_by) {
                    if (version_compare(PHP_VERSION, '7.0.0') >= 0) {
                        return $first[$order_by] <=> $second[$order_by];
                    } else {
                        $array_cmp = strcmp($first[$order_by], $second[$order_by]);
                        return -$array_cmp ;
                    }
                });
                break;
            default:
                break;
        }
        return $array;
    }

Many people are searching for a way to do this with Laravel and ending up here. Also, some Laravel questions are getting closed due to duplicates to this question. Hence, I shared an easy way to perform it with Laravel collect() method.

$inventory = collect($inventory)->sortBy('price')->toArray();

For Descending order

$inventory = collect($inventory)->sortBy('price')->reverse()->toArray();

Or,

$inventory = collect($inventory)->('price')->reverse()->toArray();
Related