PHP:: Double sort an array by priority - php

My goal is to sort an array first by the string length and after that sort it again by character value without changing the priority of the length.
Here is my code:
$arr=array("an","am","alien","i");
usort($arr, function ($a, $b) { return (strlen($a) <=> strlen($b)); });
print_r($arr);
I am getting :
Array ( [0] => i [1] => an [2] => am [3] => alien )
...almost but not there)

You're missing the logic to account for sorting by character value. You can add that logic into your custom sort method:
// if lengths are the same, then sort by value
if (strlen($a) == strlen($b)) {
return $a <=> $b;
}
// otherwise, sort by length
return (strlen($a) <=> strlen($b));
You can combine this into a single line by using a ternary:
return strlen($a) == strlen($b) ? $a <=> $b : strlen($a) <=> strlen($b);
Full example (https://3v4l.org/msISD):
<?php
$arr=array("aa", "az", "an","am", "ba", "by", "alien","i");
usort($arr, function ($a, $b) {
return strlen($a) == strlen($b) ? $a <=> $b : strlen($a) <=> strlen($b);
});
print_r($arr);
outputs:
Array
(
[0] => i
[1] => aa
[2] => am
[3] => an
[4] => az
[5] => ba
[6] => by
[7] => alien
)

Related

sort two dimensional array by descending order

I have a two-dimensional array given from a db data in a custom order.
To sort the main array I'm using this:
usort($arr, function ($a, $b) {
return $a[0] <=> $b[0];
});
json_encode result:
[["2016","0000-00-00"],["2017","0000-00-00"],["2018","0000-00-00"]]
Now I need to sort items by descending order having this result:
[["2018","0000-00-00"],["2017","0000-00-00"],["2016","0000-00-00"]]
I tried to change return $a[0] <=> $b[0]; into this:
return $a[0] > $b[0];
return $a[0] < $b[0];
return $a[0] - $b[0];
return $b[0] <=> $a[0];
Nothing works. Any help?
This works (used $b[0] <=> $a[0] for sorting):
$array = json_decode('[["2016","0000-00-00"],["2017","0000-00-00"],["2018","0000-00-00"]]', TRUE);
usort($array, function($a, $b) { return $b[0] <=> $a[0]; });
print_r($array);
The result is sorted descending:
[0] => Array
(
[0] => 2018
[1] => 0000-00-00
)
[1] => Array
(
[0] => 2017
[1] => 0000-00-00
)
[2] => Array
(
[0] => 2016
[1] => 0000-00-00
)
$a[0] < $b[0] works for me.
usort($array, function($a, $b) {
return $a[0] < $b[0];
});
Live demo here

Sorting from high to low in array

Array (
[0] => Array (
[2] => 9.6
)
[1] => Array (
[497] => 11.666666666667
)
[2] => Array (
[451] => 34
)
[3] => Array (
[459] => 8.8
)
[4] => Array (
[461] => 22.5
)
)
I have this array.
How can I sort it by number value?
I tried
usort($array, function ($a, $b)
{
return $a[0] < $b[0];
});
But doesn't work.
First things first... from the manual
value_compare_func
The comparison function 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.
Emphasis on the "integer" part.
From PHP 7, you can use the spaceship operator for this.
You need to do some extra work though to address your non-sequential array keys. You can get the first value using reset()
usort($array, function($a, $b) {
return reset($b) <=> reset($a);
});
Demo ~ https://3v4l.org/uni3v (doesn't work in PHP 5.x)
The pre PHP 7 version can be achieved with a simple subtraction. For example
return reset($b) - reset($a);
Try this:
$numbers = [1, 3, 2];
usort($numbers, function ($a, $b) {
return $a < $b ? 1 : ($a === $b ? 0 : -1);
});
print_r($numbers);
Result is:
Array
(
[0] => 3
[1] => 2
[2] => 1
)

PHP - Sort arrays by keys and values

Hello how to sort arrays by keys and values too... so if user input this value
$input = array(0,1,0,2,0);
then the result should be like this since they're the same input they should maintain their keys too...
Array
(
[0] => 0
[2] => 0
[4] => 0
[1] => 1
[3] => 2
)
not like this... the keys is jumbled and I really that key to work on my project of FCFS Scheduling.
Array
(
[4] => 0
[0] => 0
[2] => 0
[1] => 1
[3] => 2
)
btw I used asort. someone help me how to fix this?
function cmp($a, $b)
{
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
$a = array(0,1,0,2,0);
usort($a, "cmp");
foreach ($a as $key => $value) {
echo " $value\n";
}
Stable sort would help here. But php don't have any stable sorting functions since 4.1.
But you can use uksort + closure.
$input = array(0,1,0,2,0);
$cmp = function($a, $b) use($input){
if($input[$a] > $input[$b]){return 1;}
elseif($input[$a] < $input[$b]){return -1;}
elseif($a>$b){return 1;}
elseif($a<$b){return -1;}
return 0;
};
uksort($input, $cmp);
print_r($input);
https://eval.in/145923
Or shorter version
$cmp = function($a, $b) use($input){
return (($input[$a]-$input[$b])?:($a-$b));
};
Simple use the sort function
$input = array(0,1,0,2,0);
sort($input);
Result:-
Array
(
[0] => 0
[1] => 0
[2] => 0
[3] => 1
[4] => 2
)

Sorting array keeping even values on top PHP

I have tried sorting the below array to keep the even values on top and in sorted order from asc to desc
$array = array(1,2,3,4,5,6,7,8,9,10);
I tried this to sort the array
usort($array, function($a, $b) {
if ($a % 2 == 0 )
{
return 1 ;
}
else
{
return -1;
}
}
);
I got the output like below
Array
(
[0] => 7
[1] => 9
[2] => 1
[3] => 5
[4] => 3
[5] => 2
[6] => 4
[7] => 6
[8] => 8
[9] => 10
)
And I want the output array to be
Array
(
[0] => 2
[1] => 4
[2] => 6
[3] => 8
[4] => 10
[5] => 1
[6] => 3
[7] => 5
[8] => 7
[9] => 9
)
The even and odd values should be sorted in asc to desc order but keep the even values on top of odd values
usort is not stable. The documentation states:
If two members compare as equal, their relative order in the sorted array is undefined.
So, what you can do is:
usort($array, function($a, $b) {
if ($a % 2 == $b % 2) {
return intval($a - $b);
}
elseif ($a % 2 == 0 )
{
return -1 ;
}
else
{
return 1;
}
}
);
This compares the actual values if both are even or both are odd.
I think you need a somewhat more complex function. Because when you look at it there are different cases to take care of and in every one of them something different must happen:
$a and $b both are even: default numeric comparison
$a and $b both are odd: default numeric comparison
$a is even, $b is odd: $a is always smaller than $b
$a is odd, $b is even: $b is always smaller than $a
And for the implementation see the answer of fab.
A bit lenghty but works fine for me:
$array = array(1,2,3,4,5,6,7,8,9,10);
$even =array();
$odd = array();
foreach ($array as $item) {
if($item%2==0) {
$even[] = $item;
}
else {
$odd[] = $item;
}
}
usort($even);
usort($odd);
$array_sort = array_merge($even,$odd);
print_r($array_sort);
usort($array, function($a, $b) {
if ($a % 2 == $b % 2) {
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
} elseif ($a % 2 == 0) {
return -1 ;
} else {
return 1;
}
}
);
Short and simple way to write it:
<?php
$array = array(1,2,3,4,5,6,7,8,9,10);
usort($array, function($a, $b){
if ($a % 2 == $b % 2) {
return $a - $b;
}
return $a % 2 != 0;
});
print_r($array);
?>
or with a ternary:
<?php
$array = array(1,2,3,4,5,6,7,8,9,10);
usort($array, function($a, $b){
return ($a % 2 == $b % 2) ? ($a - $b) : ($a % 2 != 0);
});
print_r($array);
?>
For the comparison function, first take the difference of the mod 2 values of the two numbers.
It will be -1, 0, or 1. If it's not zero, then one number is even and the other is odd, so you can return that value. (That will sort odds above evens.)
If it is zero, then either both numbers are even or both numbers are odd, and you need to take the difference of the two numbers to break the tie.
A concise way to write this is:
usort($array, function($a, $b) {
return $a % 2 - $b % 2 ?: $a - $b;
});
To sort odd numbers at the beginning instead, swap $a and $b in the first comparison.
return $b % 2 - $a % 2 ?: $a - $b;

PHP Array sorting using child nodes?

Ok I have the following array:
Array
(
[0] => Array
(
[id] => 6
[name] => This Course
[time] => 1288082700
[description] => blah blah .
[link] => http://this.com/?g=5
[course] => 22
)
[1] => Array
(
[id] => 2
[name] => Workshop
[time] => 1287561600
[description] => This description
[link] => http://this.com/?g=5
[session] => 8
[course] => 23
[type] => standard
[adobelink] =>
)
)
How can I sort this entire array by using the inner 'time' key ?
Thanks!
You can use the usort function as:
function cmp($a,$b) {
return $a['time'] - $b['time'];
}
usort($arr,'cmp');
Working link
Use usort():
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.
Example:
function cmp($a, $b) {
if ($a['time'] == $b['time']) {
return 0;
}
return ($a['time'] < $b['time']) ? -1 : 1;
}
usort($array, 'cmp');
Of course this will fail if an array has no time element. What should happen then depends on your requirements so I will leave the error handling to you ;)
Use PHP usort() function: http://php.net/manual/en/function.usort.php
First, define a function that will decide on compare result for your data structure:
function cmp($a, $b)
{
if ($a['time'] == $b['time']) {
return 0;
}
return ($a['time'] < $b['time']) ? -1 : 1;
}
Then call usort() and give the nmae of your function to it:
usort($array, "cmp");
You're done!
uasort() will maintain your keys1.
uasort($a, function($a, $b) {
$a = $a['time']; // Assuming keys exist
$b = $b['time'];
if ($a == $b) {
return 0;
} else {
return $a < $b ? -1 : 1; // Reverse < if sort order is wrong
}
});
Anonymous function syntax requires PHP 5.3+! Pass the name of the comparison function if <5.3 (see other answers).
1) In case you care about the keys, too. If not, just use the usort() approach found in abundance above :) The comparison function are basically identical (except for #codaddict's elegant approach).
http://dk.php.net/usort
function sortByTime($a, $b)
{
if ($a['time'] > $b['time'])
{
return 1;
}
else if ($a['time'] < $b['time'])
{
return -1;
}
return 0;
}
usort($yourArray, 'sortByTime');

Categories