# Sorting Multidimensional Arrays With Uasort

Viewed   101 times

Currently I have some multidimensional arrays that look like this

``````Array (
 => Array ( [author] => 2 [date] => 1392867376 )
 => Array ( [author] => 2 [date] => 1392868188 )
 => Array ( [author] => 14 [date] => 1392867388)
 => Array ( [author] => 2 [date] => 1392870805 )
)
``````

I would like to sort them by the "date" but I have no idea how. I have tried this:

``````function cmp(\$a, \$b) {
if (\$a == \$b) {
return 0;
}
return (\$a < \$b) ? -1 : 1;
}
uasort(\$visited, 'cmp');
``````

But since I have no idea, and could not find a reference on how to use the "comparison function" I'm up in space. All I've been able to find was very vague stuff. Currently this sorts by "author".

Can someone kindly explain to me how these comparison functions work (or point me to an online resource) and tell me what I need to do to sort this array by "date" - while keeping all keys intact (keys must not be changed or erased)

Many thanks for any help provided.

PS: I have tried array_multisort - It erased my keys.

1

try this cmp function:

``````function cmp(\$a, \$b) {
if (\$a['date'] == \$b['date']) {
return 0;
}
return (\$a['date'] < \$b['date']) ? -1 : 1;
}
``````

It should work.

Thursday, August 25, 2022

4

Use usort like this:

``````\$result = array();

\$result["prio"] = 1;
\$result["date"] = '2010-02-28';
\$result["post"] = "February's thoughts";

\$result["prio"] = 0;
\$result["date"] = '2010-04-20';
\$result["post"] = "April's thoughts";

\$result["prio"] = 0;
\$result["date"] = '2010-05-30';
\$result["post"] = "May's thoughts";

function fct(\$a ,\$b) {

if (\$a['prio'] < \$b['prio']) {
return -1;
} elseif  (\$a['prio'] > \$b['prio']) {
return 1;
} else {
return strcmp(\$b['date'], \$a['date']);
}

}

usort(\$result, "fct");
print_r(\$result);
``````

Output:

``````Array
(
 => Array
(
[prio] => 0
[date] => 2010-05-30
[post] => May's thoughts
)

 => Array
(
[prio] => 0
[date] => 2010-04-20
[post] => April's thoughts
)

 => Array
(
[prio] => 1
[date] => 2010-02-28
[post] => February's thoughts
)

)
``````
Sunday, November 20, 2022

1

Use `usort` like so:

``````function myComp(\$a, \$b) {
if(\$a == \$b) {
return 0;
}

return (\$a > \$b) ? -1 : 1;
}

usort(\$myArray, 'myComp');
``````
Sunday, October 2, 2022

3

I decided to rewrite my answer to accommodate both filtering and sorting. I took a heavily object oriented approach to solving this problem, which I will detail below.

You can see all of this code in action at this ideone.com live demonstration.

The first thing I did was define two interfaces.

``````interface Filter {
public function filter(\$item);
}

interface Comparator {
public function compare(\$a, \$b);
}
``````

As their names suggest, `Filter` is used for filtering, and `Comparator` is used for comparing.

Next, I defined three concrete classes that implements these interfaces, and accomplish what I wanted.

First is `KeyComparator`. This class simply compares the key of one element to the key of another element.

``````class KeyComparator implements Comparator {
protected \$direction;
protected \$transform;
protected \$key;

public function __construct(\$key, \$direction = SortDirection::Ascending, \$transform = null) {
\$this->key = \$key;
\$this->direction = \$direction;
\$this->transform = \$transform;
}

public function compare(\$a, \$b) {
\$a = \$a[\$this->key];
\$b = \$b[\$this->key];

if (\$this->transform) {
\$a = \$this->transform(\$a);
\$b = \$this->transform(\$b);
}

return \$a === \$b ? 0 : ((\$a > \$b ? 1 : -1) * \$this->direction);
}
}
``````

You can specify a sort direction, as well as a transformation to be done to each element before they are compared. I defined a helped class to encapsulate my `SortDirection` values.

``````class SortDirection {
const Ascending = 1;
const Descending = -1;
}
``````

Next, I defined `MultipleKeyComparator` which takes multiple `KeyComparator` instances, and uses them to compare two arrays against each other. The order in which they are added to the `MultipleKeyComparator` is the order of precedence.

``````class MultipleKeyComparator implements Comparator {
protected \$keys;

public function __construct(\$keys) {
\$this->keys = \$keys;
}

public function compare(\$a, \$b) {
\$result = 0;

foreach (\$this->keys as \$comparator) {
if (\$comparator instanceof KeyComparator) {
\$result = \$comparator->compare(\$a, \$b);

if (\$result !== 0) return \$result;
}
}

return \$result;
}
}
``````

Finally, I created `MultipleKeyValueFilter` which is meant to filter an array based on an array of key/value pairs:

``````class MultipleKeyValueFilter implements Filter {
protected \$kvPairs;

public function __construct(\$kvPairs) {
\$this->kvPairs = \$kvPairs;
}

public function filter(\$item) {
\$result = true;

foreach (\$this->kvPairs as \$key => \$value) {
if (\$item[\$key] !== \$value)
\$result &= false;
}

return \$result;
}
}
``````

Now, given the input array (Notice I rearranged them a bit to make the sorting obvious):

``````\$array = array (
'1' => array ('type' => 'blah2', 'category' => 'cat2', 'exp_range' => 'this_week' ),
'2' => array ('type' => 'blah1', 'category' => 'cat1', 'exp_range' => 'this_week' ),
'3' => array ('type' => 'blah1', 'category' => 'cat2', 'exp_range' => 'next_week' ),
'4' => array ('type' => 'blah1', 'category' => 'cat1', 'exp_range' => 'next_week' )
);
``````

Sorting can be achieved by doing the following:

``````\$comparator = new MultipleKeyComparator(array(
new KeyComparator('type'),
new KeyComparator('exp_range')
));

usort(\$array, array(\$comparator, 'compare'));

echo "Sorted by multiple fieldsn";
print_r(\$array);
``````

Filtering can be achieved by doing the following:

``````\$filter = new MultipleKeyValueFilter(array(
'type' => 'blah1'
));

echo "Filtered by multiple fieldsn";
print_r(array_filter(\$array, array(\$filter, 'filter')));
``````

At this point I've given you a great deal of code. I'd suggest that your next step is to combine these two pieces into a single class. This single class would then apply both filtering and sorting together.

Monday, August 29, 2022

5

You are right, the function you're looking for is `array_multisort()`.

Here's an example taken straight from the manual and adapted to your case:

``````\$price = array();
foreach (\$inventory as \$key => \$row)
{
\$price[\$key] = \$row['price'];
}
array_multisort(\$price, SORT_DESC, \$inventory);
``````

As of PHP 5.5.0 you can use `array_column()` instead of that foreach:

``````\$price = array_column(\$inventory, 'price');

array_multisort(\$price, SORT_DESC, \$inventory);
``````
Saturday, October 1, 2022