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);
Related
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 search for '01.' that begins with the number of the array.
Expected output:
1 => string '01.02' (length=5)
2 => string '01.03' (length=5)
3 => string '01.04' (length=5)
32 => string '02.02' (length=5)
33 => string '02.03' (length=5)
34 => string '02.04' (length=5)
35 => string '02.05' (length=5)
My code:
$key = array_search('/^01./', $tomb_datum);
echo $key;
var_dump($key);
These preg match not work.
There is a function dedicated for just this purpose, preg_grep. It will take a regular expression as first parameter, and an array as the second.
See the below example: FIDDLE
$haystack = array (
'01.02',
'01.03',
'02.05',
'02.07'
);
$matches = preg_grep ('/^01/i', $haystack);
print_r ($matches);
If you're looking to filter the array, use array_filter:
$resultArray = array_filter($array, function($elm) {
if (preg_match('/^01/', $elm)) {
return true;
}
return false;
});
Hope this helps.
You could use T-Regx library which allows for all sorts of array filters:
pattern('^01.')->forArray($tomb_datum)->filter()
You can also use other methods like:
filter() - for regular (sequential) arrays
filterAssoc() - for associative arrays (filterAssoc() preserves keys)
filterByKeys() - to filter an array by keys, not values
PS: Notice that with T-Regx you don't need /.?/ delimiters!
Take a look at the following code:
$a = json_decode('{"0":"xy"}', true);
This will return an associative array like [0 => "xy"].
Is there a way not to automatically convert the keys to numbers? The result I'd like to have would be the array ["0" => "xy"] with strings as keys exclusively.
First decode it as an object (without true parameter) and then typecast it as array:
$a = (array) json_decode('{"0":"xy"}');
var_dump($a);
Ouput:
array (size=1)
'0' => string 'xy' (length=2)
Not really sure why you would want numerical array keys to be strings. It can make life harder when trying to search through an array by key or rekey the array.
However, if you really want your keys to be strings this should help
$array = json_decode('{"0":"xy"}', true);
foreach($array as $key => $value) {
$newArray[(string) $key] = $value;
}
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");
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
)