namespace App\Controllers\Redis;
class getArray{
public function sortArray(){
$sortMe = Array
(
'05' => 100,
'15' => 1,
'24' => 10,
'32' => 1000,
);
$sorted= Array
(
'0' => 1,
'1' => 10,
'2' => 100,
'3' => 1000,
);
function cmp($a, $b) {
//I need to get $sorted here
return array_search($a, $sorted) - array_search($b, $sorted);
}
usort($sortMe , 'App\Controllers\Redis\cmp');//pass the $sorted parameter
}
}
How can I pass the array parameter with namespace as all others reference I found are without namespace so I am lost. Appreciate any advice.
what I tried:
private $sorted = []; //declace a private var in the class
$this->sorted= Array
(
'0' => 1,
'1' => 10,
'2' => 100,
'3' => 1000,
);
function cmp($a, $b) {
$sorted = $this->sorted;
return array_search($a, $sorted) - array_search($b, $sorted);
}
but this will return PHP error : PHP Fatal error: Uncaught Error: Using $this when not in object context
PHP editor Link:
The expected result : https://3v4l.org/gbbua#v7.0.14
My current program : https://3v4l.org/1Kmoq#v7.0.14
Namespaces or classes have very little to do with anything here. You just want an anonymous callback:
$sortMe = array(...);
$sorted = array(...);
usort($sortMe , function ($a, $b) use ($sorted) {
return array_search($a, $sorted) - array_search($b, $sorted);
});
Related
I have an array where it's keys are the sizes and values are either 'in-stock' or 'no-stock'.
Example array:
$data = [
'L' => 'in-stock',
'S' => 'in-stock',
'XL' => 'no-stock',
'M' => 'in-stock',
];
I'm trying to sort this by size. Expected output is:
$data = [
'S' => 'in-stock',
'M' => 'in-stock',
'L' => 'in-stock',
'XL' => 'no-stock',
];
I've been looking at other similar questions but with no success because those had different array structures.
I'm struggling with the uksort function since what I want is to sort the array and preserve the keys.
uksort($data, function($a, $b) use ($data) {
static $sizes;
// filter out only used size values => ['S', 'M', 'L', 'XL']
$sizes = array_filter(["XXS", "XS", "S", "M", "L", "XL", "XXL", "XXXL"], function($arr) use ($data) {
return array_key_exists($arr, $data);
});
$sizes = array_values($sizes);
if (array_search($a, $sizes) === array_search($b, array_keys($data))) {
return 0;
}
if (array_search($a, $sizes) < array_search($b, array_keys($data))) {
return -1;
}
if (array_search($a, $sizes) > array_search($b, array_keys($data))) {
return 1;
}
});
Result:
Array
(
[S] => in-stock
[L] => in-stock
[XL] => in-stock
[M] => in-stock
)
Im trying to compare key positions in $data and defined sort order in $sizes. It does not work and i'm struggling to fully understand how to properly compare $a and $b in the uksort callback.
https://www.php.net/manual/en/function.uksort.php
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.
If you have a definite order, don't use it for sorting, but rather for mapping. E.g.:
$data = [
'L' => 'in-stock',
'S' => 'in-stock',
'XL' => 'no-stock',
'M' => 'in-stock',
];
function getOrderedBySize(array $data): array {
$result = [];
foreach (["XXS", "XS", "S", "M", "L", "XL", "XXL", "XXXL"] as $key) {
if (array_key_exists($key, $data)) {
$result[$key] = $data[$key];
}
}
return $result;
}
print_r($data);
print_r(getOrderedBySize($data));
Though if you absolutely wanted to sort the input array, this will do:
$fixedOrder = array_flip(["XXS", "XS", "S", "M", "L", "XL", "XXL", "XXXL"]);
uksort($data, static fn(string $a, string $b): int => $fixedOrder[$a] <=> $fixedOrder[$b]);
print_r($data);
You need to use the uasort function (user-associative-sort), not uksort.
uasort($array, function($a, $b) {
return $a >= $b;
});
The function will receive two items.
So, in a more complicated case, say you want to sort rows of the format
[ 'size' => 'L', 'name' => 'Xyzzy' ]
you would do
uasort($array, function($row1, $row2) {
$keys = [ 'size' => 1, 'name' => -1 ];
foreach ($keys as $name => $order) {
if ($row1[$name] < $row2[$name]) {
return $order;
}
if ($row1[$name] === $row2[$name]) {
continue;
}
return -1*$order;
}
return 0;
});
which would allow to sort one key ascending, then another key descending. You can wrap this in a different function:
function flexsort(&$array, $order) {
uasort($array, function($row1, $row2) use($order) {
foreach ($order as $name => $order) {
if ($row1[$name] < $row2[$name]) {
return $order;
}
if ($row1[$name] === $row2[$name]) {
continue;
}
return -1*$order;
}
return 0;
});
};
Then:
flexsort($allRows,[ 'size' => 1, 'name' => -1 ]);
Can anyone help?
I am trying to print out the longest string and second longest string in php
function findLongestStringFromArray($array = array()) {
if(!empty($array)){
$length_of_arr = array_map('strlen', $array);
$maxLength = max($length_of_arr); // find highest value in the array
$key = array_search($maxLength, $length_of_arr);
$key2 = array_search(next($maxLength), $length_of_arr);
return array(
'length' => $maxLength,
'postion' => $key,
'longest-string'=>$array[$key],
'secondLongest-string'=>$array[$key2]
);
}
}
$arrData = array("car", "paper", "pencil", "football", "databases");
print_r(findLongestStringFromArray($arrData));
And then i get this error message
Warning: next() expects parameter 1 to be array, integer given in C:\xampp\htdocs\php\lab2.php on line 134
Array ( [length] => 13 [postion] => 4 [longest- string] => databases [secondLongest-string] => car)
I would suggest a different approach. Sort the input array in descending order by strlen, and then return the first two elements with array_slice.
function findLongestStringFromArray($array = array()) {
usort($array, function($a, $b) {
return strlen($b) - strlen($a);
});
$longest = array_slice($array, 0, 2);
return array_combine(['longest-string','secondLongest-string'], $longest);
}
To include the length and position as well, you'd need to use uasort instead of usort to preserve the keys.
function findLongestStringFromArray($array = array()) {
uasort($array, function($a, $b) {
return strlen($b) - strlen($a);
});
return [
'length' => strlen(reset($array)),
'position' => key($array),
'longest-string' => reset($array),
'secondLongest-string' => next($array)
];
}
What is the best way to sort a php array using 2 custom sequential ordering:
$valueOrder = array('dev1', 'com', 'check', 'data');
$titleOrder = array('title4', 'title7', 'title3', 'title9');
$array = array(
array('value' => 'com', 'title' => 'title7'),
array('value' => 'dev1', 'title' => 'title9'),
array('value' => 'dev1', 'title' => 'title7'),
array('value' => 'data', 'title' => 'title4'),
);
I like this solution but it works only for one custome order :
usort($array, function ($a, $b) use ($valueOrder) {
$pos_a = array_search($a['value'], $valueOrder);
$pos_b = array_search($b['value'], $valueOrder);
return $pos_a - $pos_b;
});
var_dump($array);
it's possible to use the same solution using $valueOrder and $titleOrder ???
In the user defined custom sort function, you compare the items by value and if that value is the same, then compare by label. But, you should be aware that array_search returns FALSE in case the needle is not found so arithmetic operations will not distinguish FALSE from ZERO.
usort($array, function ($a, $b) use ($valueOrder, $titleOrder) {
$pos_a = search($a['value'], $valueOrder);
$pos_b = search($b['value'], $valueOrder);
if ($pos_a === $pos_b) {
return search($a['title'], $titleOrder) - search($b['title'], $titleOrder);
}
return $pos_a - $pos_b;
});
//just like array_search but more friendly to comparison
function search($needle, $heystack)
{
$pos = array_search($needle, $heystack);
if (false === $pos) {
return PHP_INT_MAX;
}
return $pos;
}
It is strange with asort, I want to sort the items in an array by their value,
$items = Array ( "1" => 10 , "11" => 10, "22" => 10 );
// Sort an array and maintain index association.
asort($items);
var_dump($items);
So since all values are the same, then asort shouldn't doing anything (I assume), but the result I get,
array (size=3)
22 => string '10' (length=2)
11 => string '10' (length=2)
1 => string '10' (length=2)
It reverses the order!? Why?
what I want (I think it should be like this),
array (size=3)
1 => string '10' (length=2)
11 => string '10' (length=2)
22 => string '10' (length=2)
Any ideas?
EDIT:
I tried with this below,
// Comparison function
private function cmp($a, $b) {
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
...
// Sort an array and maintain index association.
uasort($items, array($this, "cmp"));
But I still get the same 'error' result....
Since the version 4.1.0 PHP sort is not stable due to sorting algorithm, which cannot take into account both value and key. You have to use your own implementation of comparison considering key in case of equal values. For example you can modify original array values into (key, value) pairs, sort array and transform it into single dimensional back.
$items = ["1" => 10, "11" => 10, "22" => 10];
$callback = function ($a, $b) use ($callback) {
$result = $a['value'] - $b['value'];
if ($result == 0) {
$result = $a['key'] - $b['key'];
}
return $result;
};
array_walk($items, function (&$value, $key) {
$value = ["key" => $key, "value" => $value];
});
usort($items, $callback);
$items = array_combine(array_column($items, 'key'), array_column($items, 'value'));
print_r($items);
How can I sort an associative array by one of its values?
For example:
$arr = array(
'ted' => array( 'age' => 27 ),
'bob' => array( 'age' => 18 ),
'jay' => array( 'age' => 24 )
);
$arr = ???
foreach ($arr as $person)
echo $person['age'], ', ';
So that the output is:
18, 24, 27
This is an oversimplified example just to demonstrate my question.
I still require that $arr is an associative array.
The uasort() function allows you to specify a callback function, which will be responsible of doing the comparison between two elements -- so, should do just well, if you implement the proper callback function.
Here, you'd have to implement a callback function that will receive two arrays -- and compmare the age item :
function callback($a, $b) {
if ($a['age'] > $b['age']) {
return 1;
} else if ($a['age'] < $b['age']) {
return -1;
}
return 0;
}
Using that function in the following portion of code :
$arr = array(
'ted' => array( 'age' => 27 ),
'bob' => array( 'age' => 18 ),
'jay' => array( 'age' => 24 )
);
uasort($arr, 'callback');
var_dump($arr);
You would get you this resulting array :
array
'bob' =>
array
'age' => int 18
'jay' =>
array
'age' => int 24
'ted' =>
array
'age' => int 27
This is a classical example where PHP 5.3 anonymous functions come in handy:
uasort($arr, function($a, $b) {
return $a['age'] - $b['age'];
});
The $a['age'] - $b['age'] is a small trick. It works because the callback function is expected to return a value < 0 is $a is smaller than $b and a value > 0 if $a is bigger than $b.
Since you're sorting on a value inside a sub array, there's not a built-in function that will do 100% of the work. I would do a user-defined sort with:
http://www.php.net/manual/en/function.uasort.php
Here's an example comparison function that returns its comparison based on this value in the nested array
<?php
// Comparison function
function cmp($left, $right) {
$age1 = $left['age'];
$age2 = $right['age'];
if ($age1 == $age2) {
return 0;
}
return ($age1 < $age2) ? -1 : 1;
}
uasort($array, 'cmp');
http://www.php.net/manual/en/array.sorting.php
This particular case will involve using one of the sort methods that use a callback to sort
You're not just sorting an associative array, you're sorting an associative array of associative arrays ;)
A uasort call is what you're after
uasort($array, function ($a, $b) {
if ($a['age'] === $b['age']) {
return 0;
}
return $a['age'] > $a['age'] ? 1 : -1;
});