# Sort an array of associative arrays by multiple columns using a combination of ascending, descending, regular, numeric, and natural sorting

Is it possible to sort a multidimensional array by multiple columns using natural sort in PHP? Here is an example. Suppose I have a 2D array of data, e.g.,

``````\$array['Name'] = 'John';
\$array['Age'] = '20';
\$array['Code'] = 'ABC 12';

\$array['Name'] = 'John';
\$array['Age'] = '21';
\$array['Code'] = 'ABC 1';

\$array['Name'] = 'Mary';
\$array['Age'] = '20';
\$array['Code'] = 'ABC 10';
``````

I want to sort this array by name (ASC), then by age (DESC), and by code (ASC), all will be sorted naturally. Basically that will be array_multisort with natural sort.

I found many solutions about this topic on the web. Unfortunately, they only support sorting by one column, not multiple column.

## Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

### Solution 1

I think you have to implement a custom comparison function for this behavior:

``````function myCmp(\$a, \$b) {
\$nameCmp = strnatcasecmp(\$a['Name'], \$b['Name']);
\$ageCmp = strnatcasecmp(\$a['Age'], \$b['Age']);
\$codeCmp = strnatcasecmp(\$a['Code'], \$b['Code']);

if (\$nameCmp != 0) // Names are not equal
return(\$nameCmp);

// Names are equal, let's compare age

if (\$ageCmp != 0) // Age is not equal
return(\$ageCmp * -1); // Invert it since you want DESC

// Ages are equal, we don't need to compare code, just return the comparison result
return(\$codeCmp);
}
``````

Then you can call `usort(\$array, 'myCmp');` and should get the desired sorting

### Solution 2

If you’re using PHP 5.4 or newer, you can use `array_multisort` with the `SORT_NATURAL` flag.

### Solution 3

Only one of the three sorting rules actually requires natural sorting. In fact, if you use PHP’s 3-way comparison operator (`<=>`), then it will automatically compare numeric strings as numeric values. Only the third rule needs natural sorting to be explicitly declared because it demands the comparison of alphanumeric strings.

Code: (Demo)

``````\$array = [
1 => ['Name' => 'John', 'Age' => '20', 'Code' => 'ABC 12'],
2 => ['Name' => 'John', 'Age' => '21', 'Code' => 'ABC 1'],
3 => ['Name' => 'Mary', 'Age' => '20', 'Code' => 'ABC 10'],
4 => ['Name' => 'John', 'Age' => '20', 'Code' => 'ABC 1'],
5 => ['Name' => 'John', 'Age' => '20', 'Code' => 'ABC 100'],
6 => ['Name' => 'John', 'Age' => '20', 'Code' => 'ABC 2'],

];

uasort(
\$array,
fn(\$a, \$b) =>
[\$a['Name'], \$b['Age']] <=> [\$b['Name'], \$a['Age']] // name (ASC) then by age (DESC)
?: strnatcasecmp(\$a['Code'], \$b['Code']) // then by code (ASC / naturally)
);
var_export(\$array);
``````

Output:

``````array (
2 =>
array (
'Name' => 'John',
'Age' => '21',
'Code' => 'ABC 1',
),
4 =>
array (
'Name' => 'John',
'Age' => '20',
'Code' => 'ABC 1',
),
6 =>
array (
'Name' => 'John',
'Age' => '20',
'Code' => 'ABC 2',
),
1 =>
array (
'Name' => 'John',
'Age' => '20',
'Code' => 'ABC 12',
),
5 =>
array (
'Name' => 'John',
'Age' => '20',
'Code' => 'ABC 100',
),
3 =>
array (
'Name' => 'Mary',
'Age' => '20',
'Code' => 'ABC 10',
),
)
``````

Note the the first level keys are preserved in the output because `uasort()` is used. Because the input array is not indexed, I am assuming that the keys are ids or something otherwise important.

If you are comfortable with reindexing the parent level keys, then `array_multisort()` can be used after generating arrays of columnar data. (Demo)

``````foreach (\$array as ['Name' => \$names[], 'Age' => \$ages[], 'Code' => \$codes[]]);

array_multisort(
\$names,        // ASC, REGULAR
\$ages,         // DESC, NUMERIC
SORT_DESC,
SORT_NUMERIC,
\$codes,        // ASC, NATURAL
SORT_ASC,
SORT_NATURAL,
\$array         // the array to be affected
);
var_export(\$array);
``````

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0