How to Sort a PHP Array by an Element Nested Inside

How do I sort a PHP array by an element nested inside?

You can use usort as:

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

usort($arr,"cmp");

PHP sort 2d array alphabetically by nested value

You should use usort() (i'm assuming PHP 5.3+ here):

usort($your_array, function ($elem1, $elem2) {
return strcmp($elem1['title'], $elem2['title']);
});

Edit:
I hadn't noticed you wanted to preserve index association, so you actually need to use uasort() instead, with the same parameters.

Edit2:
Here is the pre-PHP 5.3 version:

function compareElems($elem1, $elem2) {
return strcmp($elem1['title'], $elem2['title']);
}

uasort($your_array, "compareElems");

How do I sort by nested php array

I dont understand half of that code (what's all the regex for?), but to achieve desired sorted table you can simply do:

$profile = simplexml_load_file('http://andrewfinden.com/test/feed.xml');
$productions = $profile->xpath(
'/profile/repertoire/composer/work/role/production'
);

to load the XML and get the list of all productions as they appear in the XML. To sort them you can use a custom sort:

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

which will compare the startdates of the simplexml elements and sort them in descending order. And then it's only a matter of just iterating the productions:

<table>
<thead>
<tr>
<th>Year</th>
<th>Company</th>
</tr>
</thead>
<tbody>
<?php foreach ($productions as $production): ?>
<tr>
<td><?php echo htmlspecialchars($production['startdate'])?></td>
<td><?php echo htmlspecialchars($production['company'])?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>

See demo

Also see this demo for your additional requests in chat, e.g. limit productions to those with a review and sorting works by production startdate.

How to Sort a Multi-dimensional Array by Value

Try a usort. If you are still on PHP 5.2 or earlier, you'll have to define a sorting function first:

function sortByOrder($a, $b) {
return $a['order'] - $b['order'];
}

usort($myArray, 'sortByOrder');

Starting in PHP 5.3, you can use an anonymous function:

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

With PHP 7 you can use the spaceship operator:

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

Finally, in PHP 7.4 you can clean up a bit with an arrow function:

usort($myArray, fn($a, $b) => $a['order'] <=> $b['order']);

To extend this to multi-dimensional sorting, reference the second/third sorting elements if the first is zero - best explained below. You can also use this for sorting on sub-elements.

usort($myArray, function($a, $b) {
$retval = $a['order'] <=> $b['order'];
if ($retval == 0) {
$retval = $a['suborder'] <=> $b['suborder'];
if ($retval == 0) {
$retval = $a['details']['subsuborder'] <=> $b['details']['subsuborder'];
}
}
return $retval;
});

If you need to retain key associations, use uasort() - see comparison of array sorting functions in the manual.

Sort 2nd nested array by value in 3rd with php

Try with array_map to get into the nested elements and your Start Time has a 'T' character which I think cannot be used with strtotime so I've removed it:

function custom_map( $array ) {
usort( $array, function( $a, $b ) {
return ($a['Start Time']<$b['Start Time'])? -1 : 1;
});
return $array;
}

$new_array = array_map( "custom_map", $week_schedule );

var_dump($new_array);

Demo

Explanation:

Since you were interested in learning how this works, I did a few research myself and came up with this explanation:

First of all, you should know what array_map() and usort() are for.

array_map() from PHP Doc:

array_map() returns an array containing all the elements of array1
after applying the callback function to each one.

Syntax:

array array_map ( callable $callback , array $array1 [, array $... ] )

In simple words, array_map() will pass each element of your array to the callback function that you specify. And it returns an array (with the changed values, that you have done in that callback function).

Now usort(),

usort() from PHP Doc:

This function will sort an array by its values using a user-supplied comparison function. If the array you wish to sort needs to be sorted by some non-trivial criteria, you should use this function.

Syntax:

bool usort ( array &$array , callable $value_compare_func )

So, usort() basically compares each array element in order to sort it in the correct order. The line that you see here:

return ($a['Start Time']<$b['Start Time'])? -1 : 1;

basically translates as:

 if $a['Start Time'] is lesser than $b['Start Time'], then return -1 so
that $a can come before $b

with values:

$a['Start Time'] = '1899-12-30T09:00:00'; //3rd element
$b['Start Time'] = '1899-12-30T17:00:00'; //1st element

Now clearly, $a which is the third element is lesser than the 1st element $b, thus $a will be positioned before it. usort() makes check against every combination from start to end in order to sort.

Now, coming back to array_map(), the reason we are using it is because you have nested arrays.

What the array_map() actually does is, passes all your @days to the usort. And then the usort takes all your @class and sorts accordingly. If you see the following demo, where your @weeks have been taken out only @days and @class present, the above code will not work and will throw you errors of 'Start Time' not being found because you are trying to traverse through 2 nested arrays when only 1 is present:

Demo

For the above structure, the right method will be to implement usort directly without using array_map like:

Demo

Sort nested array using another array with PHP

You can flip the first array in order to know what's the order of the id's:

$order = array_flip($order);

Then you simply use usort to sort the array based on the earlier flipped array:

usort($array, static function(array $a, array $b) use ($order) {
return $order[$a['nr']] <=> $order[$b['nr']];
});

Sort and array in PHP by MULTIPLE nested values?

What you're looking for is the function usort().

There, you can supply your own comparator that can compare two elements and apply the rules you wish to use.

You were on the right track, but your comparator function can be much more elaborate:

function compare_elements($l, $r) {
if ($l['wins'] > $r['wins']) {
return -1;
} else if ($l['wins'] < $r['wins']) {
return 1;
}

// Drop to second level; it will have exited by here
// if the tie could be broken by the first rule.
// You really could've put this in an else clause, but I
// wanted to avoid excessive nesting.
if ($l['loss'] > $r['loss']) {
return 1;
} else if ($l['loss'] < $r['loss']) {
return -1;
}

// And so on until the 4th level
}

Sort multidimensional array by column value within a column

Try this...

<?php

$array = [
[
'project_id' => 1,
'earnest_money_due' => [
'value' => 1000.00,
'currency' => 'USD',
],
],
[
'project_id' => 2,
'earnest_money_due' => [
'value' => 200.00,
'currency' => 'USD',
],
],
[
'project_id' => 3,
'earnest_money_due' => [
'value' => 900.00,
'currency' => 'USD',
],
],
];

array_multisort(
array_map(
static function ($element) {
return $element['earnest_money_due']['value'];
},
$array
),
SORT_ASC,
$array
);

var_dump($array);


Related Topics



Leave a reply



Submit