usort Date Assistance - php

I am trying, unsuccessfully, to sort my list by one of my template fields ($fields[3]) which is a text input field with a date inside it. The problem is that because of the format of the date it will not sort correctly because I guess it is just comparing numbers.
I think I need to change the dateformat before sorting occurs but have so far failed to do this.
I am trying to use the usort function like so (field 3 is the one with the date in which is formatted like this dd/mm/yyyy),
if (!function_exists('do_sort')) {
function do_sort($a, $b) {
return $a->fields[3] > $b->fields[3];
}}
$data = $params['data'];
usort($data, 'do_sort');
$smarty->assign('sorted', $data);
This sorts the data but as before, because I haven't changed anything, not in the correct order. Can anyone help me reformat the date prior to sorting?
Many thanks
Chris

Managed to do it. If anyone else is interested I used the following function:
function date_compare($a, $b)
{
$t1 = strtotime($a->fields[3]);
$t2 = strtotime($b->fields[3]);
return $t1 - $t2;
}
$data = $params['data'];
usort($data, 'date_compare');
$smarty->assign('sorted', $data);

Try converting the strings to timestamps first:
function do_sort($a, $b) {
$aval = strtotime($a);
$bval = strtotime($b);
if ($aval == $bval) {
return 0;
}
return $aval < $bval ? -1 : 1;
}

Related

Sort array of time strings naturally

I need to sort an array of time strings (which are not zero padded) naturally.
Sample data:
$totlahourdat1 = ["9:30", "15:00", "13:00"];
When I try array_multisort($totlahourdat1, SORT_DESC), the data appears unchanged.
My actual code:
while($row11 = mysqli_fetch_array($hourget))
{
$totlahourdat1[] = strtotime($row11['hours']);
}
array_multisort($totlahourdat1, SORT_DESC);
foreach ($totlahourdat1 as $time) {
$totlahourdat[] = date("h:i",$time);
}
echo "<pre>";
var_dump($totlahourdat);
echo "</pre>";
Ultimately, the array data should be ordered from earliest time to latest time:
["9:30", "13:00", "15:00"]
Simply do like below:-
$time = array(0=>"9:30",1=>"15:00",2=>"13:00");
function timecompare($a,$b)
{
return strtotime($a) < strtotime($b) ? -1: 1;
}
uasort($time ,'timecompare');
print_r(array_values($time));
Output:-https://eval.in/835353
Use natsort($array) see function definition
You can use usort() to write a custom sorting function.
$times = array("9:30", "15:00", "13:00");
usort($times, function ($a, $b) {
$a = strtotime($a);
$b = strtotime($b);
if ($a == $b) {
return 0;
}
return ($a < $b) ? 1 : -1;
});
If you are using PHP7, you could use the spaceship operator to greatly reduce the size of the sorting function.
$times = array("9:30", "15:00", "13:00");
usort($times, function ($a, $b) {
return strtotime($b) <=> strtotime($a);
});
Your problem is much simpler than you think. you just forgot to use the proper order
Just Order by ASC
array_multisort($totlahourdat1, SORT_ASC);
See demo here (https://eval.in/835356)
You do not need to parse these time expressions with strtotime() or a datetime method. Just sort naturally.
Code: (Demo)
sort($totlahourdat1, SORT_NATURAL);

Sort array by numbers, when the same numbers, sort by alphabet

I am trying to solve problem with sorting.
As I´ve written to the title, I need to sort array by numbers, but when some rows have the same number, sort them by alphabet. I was trying to make this with two sorts, but when I use sort by numbers and than second one by alphabet, it doesn't work.. So I've tried to change the order of functions, but still, after number sorting, it doesn't keep alphabetical sort at all...
Could someone tell me what to edit please?
Code below:
$nodesToSort = $this->openedContextMenu->getPreparedNodes();
$labelSort = function($x, $y)
{
$xTranslated = $this->getPresenter()->translator->translate($x->label);
$yTranslated = $this->getPresenter()->translator->translate($y->label);
return strcmp($xTranslated, $yTranslated);
};
$compareSort = function ($a, $b)
{
if ($a->sort == $b->sort) {
return 0;
}
return ($a->sort < $b->sort) ? -1 : 1;
};
usort($nodesToSort, $labelSort);
usort($nodesToSort, $compareSort);
SOLVED.
I just had to merge that two functions.
$compareSort = function ($a, $b)
{
if ($a->sort == $b->sort) {
$xTranslated = $this->getPresenter()->translator->translate($a->label);
$yTranslated = $this->getPresenter()->translator->translate($b->label);
return strcasecmp($xTranslated, $yTranslated);
}
return ($a->sort < $b->sort) ? -1 : 1;
};

Keys in PHP array are not sorted numerically

I have a PHP array with keys that contain a year and week number like so:
year-week
Using the built in ksort function it's returning them like so:
ksort($array);
2011-21
2011-3
2011-44
2011-45
Is it possible to have them sorted numerically like so:
2011-3
2011-21
2011-44
2011-45
If you are using PHP >= 5.4 use ksort($array, SORT_NATURAL);
Use uksort to sort the keys, and in the callback use, strnatcmp.
uksort($array, function($a,$b){
return strnatcmp($a,$b);
});
You can use natsort
$a = array_keys($myarray);
// $a now has
// array('2011-21', '2011-3', '2011-45', '2011-44');
natsort($a);
This prints
2011-3
2011-21
2011-44
2011-45
You can then use the $a array as a reference to each element of the array that holds the data (in the example above $myarray)
You can use ksort with natural flag. (Only PHP 5.4+ supports)
ksort($array, SORT_NATURAL);
You'll get the result you want if you format them with a 2 digit week. Something more like 2011-03. See sprint_f().
I see much simpler solutions are available, but here was my initial thought:
function cmp($a, $b) {
$comp1 = explode('-', $a);
$comp2 = explode('-', $b);
$year1 = (int) $comp1[0];
$year2 = (int) $comp2[0];
$week1 = (int) $comp1[1];
$week2 = (int) $comp2[1];
if ($year1 == $year2 && $week1 == $week2) {
return 0;
} elseif ($year1 == $year2) {
return ($week1 < $week2) ? -1 : 1;
} else {
return ($year1 < $year2) ? -1 : 1;
}
}
$array = array('2011-21', '2011-3', '2011-44', '2011-45');
uasort($array, 'cmp');

how to custom sort array by a specific month key

I am sure this has been answered somewhere before but I couldn't find the answer to this exact case...
I know I can use the usort function, but can't figure out the logic to do what I want eventhough it's relatively simple
I have a dynamic area being generated as such:
$details[$pageYear][$pageMonth][] = array(
"id" => $page['id'],
"title" => $page['title']
);
I want the array $details to be eventually sorted descending by year, then by month
the month value is string (january, february, march, etc... and not numeric), which seems to be my main issue (how to sort the month 'strings' by actual order and not letter order)
any help would be greatly appreciated
sorry if this turns out to be a duplicate
can you use uasort whit this callback?
<?php
function cmp_month_strings($a_string, $b_string)
{
$a_value = strtotime("{$a_string} 2000");
$b_value = strtotime("{$b_string} 2000");
if($a_value == $b_value)
return 0;
else if($a_value < $b_value)
return -1;
else
return 1;
}
?>
To sort by key, you need uksort
Some similar way:
uksort($details, function($a, $b) {
return ($a < $b) ? -1 : 1;
});
foreach ($details as &$year) {
uksort($year, function($a, $b) {
$montha = (int) date('m', strtotime("{$a} 1 2000"));
$monthb = (int) date('m', strtotime("{$b} 1 2000"));
return ($montha < $monthb) ? -1 : 1;
});
}

PHP sort by arbitrary order [duplicate]

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 7 years ago.
I need a function in php to sort a list of words according to an arbitrary ordering.
Any words in the list not in my predefined order should be sorted alphabetically at the end of the list.
Below is my first attempt, it is neither elegant or efficient. Can you suggest a better way to acheive this?
Thanks
public static function sortWords(&$inputArray){
$order=array("Banana","Orange", "Apple", "Kiwi");
sort($inputArray);
for($i=0;$i<count($inputArray));$i++){
$ac = $inputArray[$i];
$position = array_search($ac,$order);
if($position !== false && $i != $position){
$temp=$inputArray[$position];
$inputArray[$position]=$inputArray[$i];
$inputArray[$i]=$temp;
}
}
}
PHP provides the usort() and uksort() functions to allow you to write your own sorting routines. Of these two, you'll be wanting usort().
Both these functions expect you to write a stand-alone function, which takes as input two elements of the input array, and returns the order that they should be sorted into. The usort() function then runs its own sorting algorithm, calling your function as to establish the sorting order often as required until it has sorted the entire array.
So you'd write something like this....
function mycompare($a, $b) {
if ($a == $b) {return 0;}
$order=array("Banana","Orange", "Apple", "Kiwi");
$position = array_search($a,$order);
$position2 = array_search($b, $order);
//if both are in the $order, then sort according to their order in $order...
if ($position2!==false && $position!==false) {return ($position < $position2) ? -1 : 1;}
//if only one is in $order, then sort to put the one in $order first...
if($position!==false) {return -1;}
if($position2!==false) {return 1;}
//if neither in $order, then a simple alphabetic sort...
return ($a < $b) ? -1 : 1;
}
...then just call usort($inputarray,'mycompare'); to sort them.
public static function sortWords($inputArray){
$order=array("Banana","Orange", "Apple", "Kiwi");
$sorted_array = array_diff($inputArray,$order);
sort($sorted_array);
$rest_array = array_intersect($order,$inputArray);
$result = array_merge($rest_array,$sorted_array);
return $result;
}
Haven't tested but try this.
Probably slower than Headshota's solution, but just to provide you another (not tested) possibility:
function sortWordsCmp($a, $b) {
$order=array("Banana","Orange", "Apple", "Kiwi");
$a = array_search($a, $order);
$b = array_search($b, $order);
if ($a === $b)
return 0;
return (($b===false) || ($a < $b)) ? -1 : +1;
}
public static function sortWords($inputArray){
usort($inputArray, 'sortWordsCmp');
return $inputArray;
}
public static function sortByArbitraryKeys(&$inputArray, $sort_order) {
$sort_order = array_flip($sort_order);
uksort($inputArray, function ($a, $b) use ($sort_order) {
return $sort_order[$a] - $sort_order[$b];
}
}
So an example would be the following...
// Doe, John L.
$this->full_name = ['last_name'=>'Doe', 'first_name'=>'John', 'middle_initial'=>'L.'];
// John L. Doe
$this->sortByArbitraryKeys($this->full_name, ['first_name', 'middle_initial', 'last_name']);
You could easily refactor this for whatever your specific use case is.

Categories