Order PHP array by sub-array by date key - php

I know this question has been asked a hundred times, and I've gone through multiple answers and am not getting the correct results.
I am trying to order the following row by date, oldest first:
Array(
[0] => Array
(
[0] => '3173'
[1] => 'Contact - 12-6-14 Outstanding invoice'
[2] => '16/06/2014'
[3] => '204'
)
[1] => Array
(
[0] => '3167'
[1] => 'Contact - Outstanding invoice'
[2] => '13/06/2014'
[3] => '207'
)
[2] => Array
(
[0] => '3497'
[1] => 'New Site - Keri Keri'
[2] => '25/11/2014'
[3] => '43'
)
[3] => Array
(
[0] => '2023'
[1] => 'Analysis'
[2] => '17/06/2014'
[3] => '355'
)
[4] => Array
(
[0] => '2641'
[1] => 'PSS'
[2] => '20/02/2014'
[3] => '321'
)
)
I have tried things such as the below with no luck.
function cmp($a, $b){
return $b[2] - $a[2];
}
usort($urgent_array, "cmp");
Any help on this one would be really appreciated :)

First, you want to compare, not subtract:
function cmp($a, $b) {
if ($a[2] == $b[2])
return 0;
return ($a[2] > $b[2]) ? 1 : -1;
}
usort($urgent_array, "cmp");
Then, date ordering works best if you use the Y-m-d format:
2014-06-13 etc.

Change your compare function to
function cmp($a, $b){
$a_date = strtotime(str_replace('/', '-', $a[2]));
$b_date = strtotime(str_replace('/', '-', $b[2]));
return $a_date - $b_date;
}
You want to use strtotime because subtracting strings doesn't really mean anything. The str_replace is because PHP expects dashes for dd-mm-yyyy format.

Related

Sort array by date

My array has an array for each field (i.e date, name, etc.). How do I sort the array by date? Should I create another array? Can I use sort or unsort here. If yes, how? Here is my array:
Array
(
[date] => Array
(
[0] => 03/11/2019
[1] => 03/19/2019
[2] => 03/15/2019
[3] => 12/15/2018
)
[name] => Array
(
[0] => Lowa
[1] => Stephanie
[2] => Allan
[3] => Joffer
)
[number] => Array
(
[0] => 178989898
[1] => 111111111
[2] => 222222222
[3] => 333333333
)
[unit] => Array
(
[0] => HR
[1] => VPP
[2] =>
[3] => OAT
)
[department] => Array
(
[0] => Chemistry
[1] => IT
[2] => Lab
[3] => Contractor
)
)
At the end, my first element will be:
03/19/2019 Stephanie 111111111 VPP IT
I think your data can be better organized:
$newArr = Array
(
[0] => Array
(
[date] => 03/11/2019
[name] => Lowa
[number] => 178989898
[unit] => HR
[department] => Chemistry
)
[1] => Array
(
[date] => 03/19/2019
[name] => Stephanie
[number] => 111111111
[unit] => VPP
[department] => IT
)
[2] => Array
(
[date] => 03/15/2019
[name] => Allan
[number] => 222222222
[unit] =>
[department] => Lab
)
[3] => Array
(
[date] => 12/15/2018
[name] => Joffer
[number] => 333333333
[unit] => OAT
[department] => Contractor
)
);
Then, you can simply sort it by:
function cmp($a, $b) {
if ($a["date"] == $b["date"]) return 0;
return ($a["date"] < $b["date"]) ? -1 : 1;
}
usort($newArr, "cmp");
Please be warned that dates in the format "Month/Day/Year" ar not alphabetically sortable.
You definitively should use a Year/Month/Day format for your dates, or write a more specific cmp() function...
UPDATE: To answer OP's question in comment: just reverse $row and 'field' order:
for ($row = 0; $row < count($date); $row++) {
$newArr[$row]['date'] = $date[$row];
$newArr[$row]['name'] = $name[$row];
...
}
First save the keys of your array - then by using array_value convert to integer keys so you can use the ... operator.
Then you can use array_filter with null function to re-organize your array. Next step will be to get the keys back using array_map and array_combine.
Last step - sort by "data" with usort
Consider the following example:
$arr = ["date" => ["3", "7", "5"], "name" => ["aa", "bb", "cc"]]; // this can have a lot more sub-array inside
$keys = array_keys($arr); // extract the keys for later use
$res = array_map(null, ...array_values($arr)); // transposed the array
$res = array_map(function ($e) use ($keys) {return array_combine($keys, $e);}, $res); // return the keys to the transposed array
usort($res, function ($a, $b) {return strcmp($a['date'], $b['date']);} ); // sort all by "date"
Reference:
array-keys, array-filter, array-map, usort, array-values
Notice #MarcoS post comment regarding the comparing dates

Sort array by key value and then get 5 highest and lowest values in array

I have an array called "playersArray" that looks like this:
Array (
[0] => Array ( [name] => Joe [holders] => 0 )
[1] => Array ( [name] => Bob [holders] => 100 )
[2] => Array ( [name] => Jake [holders] => 100 )
[3] => Array ( [name] => Mike [holders] => 100 )
[4] => Array ( [name] => Tim [holders] => -0.0145 )
[5] => Array ( [name] => Frank[holders] => 100 )
[6] => Array ( [name] => Scott [holders] => 0.0583 )
[7] => Array ( [name] => Doug[holders] => 0.1308 )
[8] => Array ( [name] => Tommy [holders] => 0.2516 )
[9] => Array ( [name] => Eric [holders] => 100 )
)
I have a function to sort this array by the "holders" value:
function compareHolders($a, $b) {
$aPoints < $a['holders'];
$bPoints < $b['holders'];
return strcmp($aPoints, $bPoints);
}
I loop through another array to create this array:
foreach ($players as $player) {
$player['name'] = $athlete['name'];
$player['holders'] = $total_result_yesterday;
$playersArray[] = $player;
}
I am trying to sort the array by "holder" value:
usort($playersArray, 'compareHolders');
print_r($playersArray);
Finally, I am trying to get the 5 highest and 5 lowest "holder" values in the newly sorted array:
$first_5_players = array_slice($playersArray, 0, 5, true);
$last_5_players = array_slice($playersArray, -5);
However, the sorting is not working correctly. The values due not show in sequential order as desired. How can I get the sorting to work correctly? Thank you!
your sorting function compareHolders is not correct. $aPoints and $bPoints are not defined. Since values for holders key are numeric you can use the comparision operators. Try doing following:
function compareHolders($a, $b) {
if ($a['holders'] == $b['holders']) {
// return 0 if equal
return 0;
}
return ($a['holders'] > $b['holders']) ? -1 : 1;
}
You are not actually comparing the two values in compareHolders(), because you're not declaring $aPpoints and $bPoints.
This should work:
function compareHolders($a, $b) {
$aPoints = $a['holders'];
$bPoints = $b['holders'];
return strcmp($aPoints, $bPoints);
}
or alternatively you could just return:
return strcmp($a['holders'], $b['holders']);
And then you could get rid of the strcmp(), since you're not comparing strings.

PHP - Sort a multidimensional arrays subsubarray from value

Array
array (
[0] => array
(
[field1] => 'name'
[field2] => 'text'
[field3] => array
(
[0] => array
(
[text] => 'This arrays order is to be kept!'
[name] => 'Only sort the sub-sub-array below!'
[order] => ''
)
)
)
[1] => array
(
[field1] => 'name'
[field2] => 'text'
[field3] => array
(
[0] => array
(
[text] => '2014'
[name] => 'Dummy!'
[order] => '1'
)
[1] => array
(
[text] => '2013'
[name] => 'Try me!'
[order] => '2'
)
[2] => array
(
[text] => '1985'
[name] => 'Help!'
[order] => '5'
)
[3] => array
(
[text] => '2002'
[name] => 'Please!'
[order] => '4'
)
[4] => array
(
[text] => '2007'
[name] => 'Order!'
[order] => '3'
)
)
)
...
Goal
I want to keep the 1st and 2nd level array and it's values as is. I need to sort the keys in the 2nd sub-sub-array by the value in theorder-field. So where it says the years, that sub-sub-array should be sorted ASC or DESC. and all other keys/values/structure/map should be kept as is.
Sorted array:
array (
[0] => array
(
[field1] => 'name'
[field2] => 'text'
[field3] => array
(
[0] => array
(
[text] => 'This arrays order is to be kept!'
[name] => 'Only sort the sub-sub-array below!'
[order] => ''
)
)
)
[1] => array
(
[field1] => 'name'
[field2] => 'text'
[field3] => array
(
[0] => array
(
[text] => '2014'
[name] => 'Dummy!'
[order] => '1'
)
[1] => array
(
[text] => '2013'
[name] => 'Try me!'
[order] => '2'
)
[2] => array
(
[text] => '2007'
[name] => 'Order!'
[order] => '3'
)
[3] => array
(
[text] => '2002'
[name] => 'Please!'
[order] => '4'
)
[4] => array
(
[text] => '1985'
[name] => 'Help!'
[order] => '5'
)
)
)
Help
I've spent hours and hours of trying different custom solutions, mostly based on usort() but I've also done it knowing that none of those Q&A were describing the situation I've got.
I'm starting to doubt that it's even possible.
Does anyone know if it is? And if so, can you please shed some light or provide a hint/tutorial/example for demonstration?
Laravel 5.1
I'm retrieving this from a Laravel Model and using toArray();
Is there is a better way to achieve this in Laravel I would be glad to know.
If the sub-subarray you are wanting to sort is always identified by the same key, you can just usort the contents of that key.
foreach ($test as &$value) {
// Using a (^) reference to each value will sort the existing
// array instead of creating a sorted copy.
usort($value['field3'], function($a, $b) {
// You can use an anonymous function like this for the usort comparison function.
if ($a['order'] < $b['order']) return -1;
if ($a['order'] == $b['order']) return 0;
// In case of 'order' ties, you may want to add a comparison of a different key
return 1; // $a['order'] must be > $b['order'] at this point
});
}
Note that the comparison function used in usort:
must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
It may be better to do this using Laravel, because the database will most likely be able to do this sorting faster than PHP will, but we would need to know much more about your model setup to figure that out and that sounds like basically a totally different question.
If I understood the problem correctly, this could be a solution (in these examples $arr is the variable holding the array):
function cmp($a, $b)
{
return ($a['order'] < $b['order']) ? -1 : 1;
}
foreach($arr as $key => $subarr){
foreach($subarr as $key2 => $subsubarr){
if(is_array($subsubarr)){
usort($subsubarr,"cmp");
$subarr[$key2] = $subsubarr;
}
}
$arr[$key] = $subarr;
}
or
function cmp($a, $b)
{
return ($a['order'] < $b['order']) ? -1 : 1;
}
foreach($arr as &$subarr){
foreach($subarr as &$subsubarr){
if(is_array($subsubarr)){
usort($subsubarr,"cmp");
}
}
}

issue in sorting a date array [duplicate]

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 9 years ago.
I want to sort the array on date basis.
I used the below code to sort the array
<?php
$a=array("14-10-2013","15-10-2013","16-10-2013","13-11-2013","17-11-2013","18-10-2013","19-10-2013");
array_multisort($a);
print_r($a);
?>
this gives me the result
Array ( [0] => 13-11-2013 [1] => 14-10-2013 [2] => 15-10-2013 [3] => 16-10-2013 [4] => 17-11-2013 [5] => 18-10-2013 [6] => 19-10-2013 )
this is not the correct order.
the correct order should be
Array ( [0] => 14-10-2013 [1] => 15-10-2013 [2] => 16-10-2013 [3] => 18-10-2013 [4] => 19-10-2013 [5] => 13-11-2013 [6] => 17-11-2013 )
What should i have to do for the correct sequence of the date?
use this code :
$a=array("14-10-2013","15-10-2013","16-10-2013","13-11-2013","17-11-2013","18-10-2013","19-10-2013");
usort($a, "sortFunction");
print_r($a);
function sortFunction( $a, $b ) {
return strtotime($a) - strtotime($b);
}
OUTPUT
Array
(
[0] => 14-10-2013
[1] => 15-10-2013
[2] => 16-10-2013
[3] => 18-10-2013
[4] => 19-10-2013
[5] => 13-11-2013
[6] => 17-11-2013
)
You have a few options here.
Reverse the date: 2013-11-13 for example. You are sorting a string. So it starts with the lowest number. That will only work when you have Year-Month-Date.
You can also use timestamps. So from a timestamp, sort all the value's. After that use:
foreach($a as $key => $value) {
$a[$key] = date("d-m-Y", $value);
}
print_r($a);

PHP sort mutlidim array usort not working

Hi I need to sort an array by date:
This is my array $get:
Array (
[0] => Array (
[Date] => 02.06.2012
[Theme] => test
)
[1] => Array (
[Date] => 03.07.2012
[Theme] => lol
)
[2] => Array (
[Date] => 09.06.2012
[Theme] => hm
)
)
I tried following code:
function date_sort($a, $b) {
return strcmp($a['Date'], $b['Date']);
}
usort($get, 'date_sort');
But all I get is unordered dates. My date is set dd.mm.yyyy!
Try doing
function date_sort($a, $b) {
return strtotime($a['Date']) - strtotime($b['Date']);
}

Categories