I would like to have a unique sort function for several associative arrays.
The best candidate among the various PHP sort functions would be uksort(), (usort() would be ideal, but it changes the array keys to become the numerical index(!)).
For instance (using a simpler array)
function sorting_by_length_desc ($a, $b)
{
return strlen($GLOBALS['arr'][$b]) - strlen($GLOBALS['arr'][$a]);
}
$arr = ('chandler' => 'bing', 'monica' => 'lewinsky');
uksort($arr, 'sorting_by_length_desc');
will make $arr to be
('monica' => 'lewinsky', 'chandler' => 'bing');
without affecting the keys.
So how to use the same sort function for any array, uksort() being called at various places in the code? For instance for $arr1, $arr2, ..., $arrn?
Is it necessary to use another global var with the array name to be assigned to the array to be sorted (before the sort), and used globally in the sort function?
There must be something else, cleaner, right?
You can have a common comparison function like:
function sorting_by_length_desc ($a, $b) {
return strlen($b) - strlen($a);
}
Also uksort sorts the array on keys. Is that what you are looking for?
If you want to sort the arrays on value maintaining the key,value association you can use uasort.
You can achieve this by uksort() function
$arr = array('chandler' => 'bing', 'monica' => 'lewinsky', 'name' => 'smallest one');
uksort($arr, function($a, $b) {
return strlen($a) - strlen($b);
});
$result = $arr;
Result(sorted as smallest string length of array keys):
Array
(
[name] => smallest one
[monica] => lewinsky
[chandler] => bing
)
Related
I have some json filenames in an multidimensional array, created like this: $files[] = array("name" => $file, "type" => "json") that I want to sort ascending like this:
1.File
2.File
3.File
10.File
11.File
If I order them using php sort($files) function they will be ordered like this:
1.File
10.File
11.File
2.File
3.File
If however I use natsort($files) that quote: orders alphanumeric strings in the way a human being would (php.net), I get a total mess:
3.File
2.File
10.File
1.File
11.File
Is there some better approach to order an array using php functions? Or do I have to build a custom sorting function. The server is running PHP 7.0.
You use multidimensional array, as you can see PHP have an error (Array to string conversion), you need to use usort for that task like:
$array = array(
array("name"=>'1.File', "type" => "json"),
array("name"=>'2.File', "type" => "json"),
array("name"=>'3.File', "type" => "json"),
array("name"=>'10.File', "type" => "json"),
array("name"=>'11.File', "type" => "json"),
);
usort($array, function($a, $b) {
return ($a['name'] > $b['name'])
? 1
: ($a['name'] < $b['name'])
? -1
: 0;
});
print_r($array);
Your fiddle edited
Reference:
usort
As #u_mulder suggest strnatcasecmp will improve the code like:
usort($array, function($a, $b) {
return strnatcasecmp($a['name'], $b['name']);
});
Reference:
strnatcasecmp
I need to sort the following flat, associative array by its keys, but not naturally. I need to sort the keys by a predefined array of values.
$aShips = [
'0_204' => 1,
'0_205' => 2,
'0_206' => 3,
'0_207' => 4
];
My order array looks like this:
$order = ["0_206", "0_205", "0_204", "0_207"];
The desired result:
[
'0_206' => 3,
'0_205' => 2,
'0_204' => 1,
'0_207' => 4
]
I know how to write a custom sorting function, but I don't know how to integrate the order array.
function cmp($a, $b){
if ($a==$b) return 0;
return ($a<$b)?-1:1;
}
uasort($aShips, "cmp");
If you want to sort by keys. Use uksort. Try the code below.
<?php
$aShips = array('0_204' => 1, '0_205' => 2, '0_206' => 3, '0_207' => 4);
uksort($aShips, function($a, $b) {
return $b > $a;
});
According to the Official PHP Docs, you can use uasort() like this (just for demo):
<?php
// Comparison function
function cmp($a, $b) {
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
// Array to be sorted
$array = array('a' => 4, 'b' => 8, 'c' => -1, 'd' => -9, 'e' => 2, 'f' => 5, 'g' => 3, 'h' => -4);
print_r($array);
// Sort and print the resulting array
uasort($array, 'cmp');
print_r($array);
?>
You don't need to leverage a sorting algorithm.
Simply flip $order to use its values as keys (maintaining their order), then merge the two arrays to replace the unwanted values of $order with the values from $aShip.
This assumes that $aShip includes all key values represented in $order, of course. If not, array_intersect_key() can be used to filter $order, but this is dwelling on a fringe case not included in the posted question.
Code: (Demo)
var_export(array_replace(array_flip($order), $aShips));
Output:
array (
'0_206' => 3,
'0_205' => 2,
'0_204' => 1,
'0_207' => 4,
)
This also works when you haven't listed every occurring key in $order -- the unlisted keys are "moved to the back". Proven by this Demo.
Using a custom sorting algorithm can be done and there will be a number of ways, but I'll only show one for comparison's sake.
Reverse your order array and use it as a lookup array while asking uksort() to sort in a descending fashion. If an encountered key is not found in the lookup assign it a value of -1 to ensure it moves to the back of the array.
Code: (Demo)
$lookup = array_flip(array_reverse($order));
uksort($aShips, function($a, $b) use ($lookup) {
return ($lookup[$b] ?? -1) <=> ($lookup[$a] ?? -1);
});
var_export($aShips);
If you don't like reversing the lookup and sorting DESC, you can count the order array to determine a fallback value. This alternative script uses arrow function syntax for brevity and to gain direct access to the variables declared outside of the closure. (Demo)
$lookup = array_flip($order);
$default = count($order);
uksort($aShips, fn($a, $b) => ($lookup[$a] ?? $default) <=> ($lookup[$b] ?? $default));
var_export($aShips);
I want to sort this key-value array by values first, then keys.
This is the array:
$a = [
10 => 1,
4 => 2,
3 => 2
];
i want to get:
4 => 2,
3 => 2,
10 => 1
I tried to use arsort, but can't get current answer.
Use uksort to sort by keys, use those keys to look up the values in the array, do a comparison by values first and keys upon equality:
uksort($arr, function ($a, $b) use ($arr) {
if (($res = $arr[$a] - $arr[$b]) != 0) {
return $res;
}
return $a - $b;
});
See https://stackoverflow.com/a/17364128/476 for more in-depth explanations of sort callbacks.
I have a simple Array. The goal is, to sort them ascending by the key.
$someUnsortedArray = array("140/142" => "FirstValue", "118/120" => "SecondValue", "122/124" => "ThirdValue", "40/42" => "FourthValue");
ksort($someUnsortedArray);
My Output:
array (size=4)
'118/120' => string 'SecondValue'
'122/124' => string 'ThirdValue'
'140/142' => string 'FirstValue'
'40/42' => string 'FourthValue'
Expected Output:
array (size=4)
'40/42' => string 'FourthValue'
'118/120' => string 'SecondValue'
'122/124' => string 'ThirdValue'
'140/142' => string 'FirstValue'
What's the function in php I am searching for?
You could use uksort() in this case:
$someUnsortedArray = array("140/142" => "FirstValue", "118/120" => "SecondValue", "122/124" => "ThirdValue", "40/42" => "FourthValue");
uksort($someUnsortedArray, function($a, $b){
$a = str_replace('/', '', $a);
$b = str_replace('/', '', $b);
return $a - $b;
});
echo '<pre>';
print_r($someUnsortedArray);
As an alternative, you can also make use of the natural order string compare function to compare the keys
function sortKey($a, $b) {
return strnatcmp($a, $b);
}
uksort($someUnsortedArray,"sortKey");
Checking php manual:
http://php.net/manual/en/function.ksort.php
Use ksort() with SORT_NUMERIC flag.
$someUnsortedArray = array("140/142" => "FirstValue", "118/120" => "SecondValue", "122/124" => "ThirdValue", "40/42" => "FourthValue");
ksort($someUnsortedArray, SORT_NUMERIC);
echo '<pre>';
print_r($someUnsortedArray);
Sample Output
Use the function uksort and pass the function a custom function/method that will do the right conversion based on your needs.
Here is the PHP manual page for he function uksort
http://php.net/manual/en/function.uksort.php
The result is the expected behaviour, because if you sort Strings in alphanumerical order 1* is always before 4*.
If you want to have it sorted by number you'll have to split your string, convert the elements to number and sort them by number.
Implementation depends on what you want to achieve. Just a list of the Keys? Then you could iterate in an foreach loop adressing the keys for example.
There won't be an "out-of-the-box" PHP Function.
$someUnsortedArray = array("5/142" => "FirstValue", "118/120" => "SecondValue", "122/124" => "ThirdValue", "40/42" => "FourthValue");
uksort($someUnsortedArray, function($a, $b) {
// to avoid manipulating them as a string ....
return ((float)$a)-((float)$b);
});
var_dump($someUnsortedArray);
I am creating a template parser and i need to sort the array of variables that gets passed into the parser so that each array element that IS an array get processed first. For example:
$data = array(
'name' => 'Steven',
'type' => array(
'gender' => 'M',
'age' => 23'
)
)
I need 'type' to be first since it is an array, and 'name' to be last. Does anyone have an idea on how to do this? Ive looked at php.net's manual at the different sort functions, but dont see how any apply to my situation.
function cmp($a, $b) {
return is_array($a) ? -1 : 1;
}
uasort($data, "cmp");
This will sort the array based on the value type...alphabetically. Array comes before String.
function cmp($a, $b) {
return is_array($a)? -1 : 0;
}
uasort($data, "cmp");