PHP Sort Array By SubArray Value

PhpArraysSorting

Php Problem Overview


I have the following array structure:

Array
        (
            [0] => Array
                (
                    [configuration_id] => 10
                    [id] => 1
                    [optionNumber] => 3
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
        
            [1] => Array
                (
                    [configuration_id] => 9
                    [id] => 1
                    [optionNumber] => 2
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
        
            [2] => Array
                (
                    [configuration_id] => 8
                    [id] => 1
                    [optionNumber] => 1
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
    )

What is the best way to order the array in an incremental way, based on the optionNumber?

So the results look like:

Array
        (
            [0] => Array
                (
                    [configuration_id] => 8
                    [id] => 1
                    [optionNumber] => 1
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
        
            [1] => Array
                (
                    [configuration_id] => 9
                    [id] => 1
                    [optionNumber] => 2
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
        
            [2] => Array
                (
                    [configuration_id] => 10
                    [id] => 1
                    [optionNumber] => 3
                    [optionActive] => 1
                    [lastUpdated] => 2010-03-17 15:44:12
                )
    )

Php Solutions


Solution 1 - Php

Use usort.

function cmp_by_optionNumber($a, $b) {
  return $a["optionNumber"] - $b["optionNumber"];
}

...

usort($array, "cmp_by_optionNumber");

In PHP ≥5.3, you should use an anonymous function instead:

usort($array, function ($a, $b) {
    return $a['optionNumber'] - $b['optionNumber'];
});

Note that both code above assume $a['optionNumber'] is an integer. Use @St. John Johnson's solution if they are strings.


In PHP ≥7.0, use the spaceship operator <=> instead of subtraction to prevent overflow/truncation problems.

usort($array, function ($a, $b) {
    return $a['optionNumber'] <=> $b['optionNumber'];
});

Solution 2 - Php

Use usort

 usort($array, 'sortByOption');
 function sortByOption($a, $b) {
   return strcmp($a['optionNumber'], $b['optionNumber']);
 }

Solution 3 - Php

I used both solutions by KennyTM and AJ Quick and came up with a function that can help in this issue for many cases like using ASC or DESC sorting or preserving keys or if you have objects as children of array.

Here is this function (works for PHP7 and higher because of spaceship operator):

/**
 * @param array $array
 * @param string $value
 * @param bool $asc - ASC (true) or DESC (false) sorting
 * @param bool $preserveKeys
 * @return array
 * */
function sortBySubValue($array, $value, $asc = true, $preserveKeys = false)
{
    if ($preserveKeys) {
        $c = [];
        if (is_object(reset($array))) {
            foreach ($array as $k => $v) {
                $b[$k] = strtolower($v->$value);
            }
        } else {
            foreach ($array as $k => $v) {
                $b[$k] = strtolower($v[$value]);
            }
        }
        $asc ? asort($b) : arsort($b);
        foreach ($b as $k => $v) {
            $c[$k] = $array[$k];
        }
        $array = $c;
    } else {
        if (is_object(reset($array))) {
            usort($array, function ($a, $b) use ($value, $asc) {
                return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
            });
        } else {
            usort($array, function ($a, $b) use ($value, $asc) {
                return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
            });
        }
    }

    return $array;
}

Usage:

sortBySubValue($array, 'optionNumber', true, false);

Edit

The first part can be rewritten using uasort() and the function will be shorter (works for PHP7 and higher because of spaceship operator):

/**
 * @param array $array
 * @param string $value
 * @param bool $asc - ASC (true) or DESC (false) sorting
 * @param bool $preserveKeys
 * @return array
 * */
function sortBySubValue($array, $value, $asc = true, $preserveKeys = false)
{
    if (is_object(reset($array))) {
        $preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) {
            return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
        }) : usort($array, function ($a, $b) use ($value, $asc) {
            return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
        });
    } else {
        $preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) {
            return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
        }) : usort($array, function ($a, $b) use ($value, $asc) {
            return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
        });
    }
    return $array;
}

Solution 4 - Php

Using array_multisort(), array_map()

array_multisort(array_map(function($element) {
      return $element['optionNumber'];
  }, $array), SORT_ASC, $array);
  
print_r($array);

DEMO

Solution 5 - Php

The keys are removed when using a function like the ones above. If the keys are important, the following function would maintain it... but foreach loops are pretty inefficient.

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

Use arsort instead of asort if you want from high to low.

Code credit: http://www.firsttube.com/read/sorting-a-multi-dimensional-array-with-php/

Solution 6 - Php

PHP 5.3+

usort($array, function($a,$b){ return $a['optionNumber']-$b['optionNumber'];} );

Solution 7 - Php

A one-line solution using array_multisort and array_column.

//your array
$yourarray = Array
          (
           "0" => Array
                  (
                    "configuration_id" => 10,
                    "id" => 1,
                    "optionNumber" => 3,
                    "optionActive" => 1,
                    "lastUpdated" => "2010-03-17 15:44:12"
                  ),
           "1" => Array
                  (
                    "configuration_id" => 9,
                    "id" => 1,
                    "optionNumber" => 2,
                    "optionActive" => 1,
                    "lastUpdated" => "2010-03-17 15:44:12"
                  ),
           "2" => Array
                  (
                    "configuration_id" => 8,
                    "id" => 1,
                    "optionNumber" => 1,
                    "optionActive" => 1,
                    "lastUpdated" => "2010-03-17 15:44:12"
                  )
);

//access optionNumber in the child arrays using array_column
array_multisort(array_column($yourarray, 'optionNumber'), SORT_ASC, $yourarray);

//print out preformatted
echo "<pre>"; print_r($images); echo "</pre>";

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSjwdaviesView Question on Stackoverflow
Solution 1 - PhpkennytmView Answer on Stackoverflow
Solution 2 - PhpSt. John JohnsonView Answer on Stackoverflow
Solution 3 - PhpPigalev PavelView Answer on Stackoverflow
Solution 4 - PhpGhanshyam NakiyaView Answer on Stackoverflow
Solution 5 - PhpAJ QuickView Answer on Stackoverflow
Solution 6 - PhpSamer AtaView Answer on Stackoverflow
Solution 7 - PhpgarrettlynchirlView Answer on Stackoverflow