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
)
Related
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
)
Here is my array:
$arrayA = array(0 => "someString",
1 => "otherString",
2 => "2017",
3 => "anotherString",
4 => "2016");
My goal is to to find the first item that has a numeric value (which would be "2017") and place it first in the array, without changing its original key and keeping the others in the same order.
So I want:
$arrayA = array(2 => "2017",
0 => "someString",
1 => "otherString",
3 => "anotherString",
4 => "2016");
I tried uasort() php function and it seems the way to do it, but I could not figure out how to build the comparison function to go with it.
PHP documentation shows an example:
function cmp($a, $b) {
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
But, WHO is $a and WHO is $b?
Well, I tried
function my_sort($a,$b) {
if ($a == $b ) {
return 0;
}
if (is_numeric($a) && !is_numeric($b)) {
return -1;
break;
}
}
But, of course, I am very far from my goal. Any help would be much appreciated.
You don't need to sort per se. Once you find the element in question, you can simply push it onto the front of the array with the + operator:
foreach ($arrayA as $k => $v) {
if (is_numeric($v)) {
$arrayA = [$k => $v] + $arrayA;
break;
}
}
print_r($arrayA);
Yields:
Array
(
[2] => 2017
[0] => someString
[1] => otherString
[3] => anotherString
[4] => 2016
)
How to sort multidimensional array. This is what my array looks like
[0] => Array
(
[id] => 1
[title] => 3A
[active] => 1
)
[1] => Array
(
[id] => 1
[title] => A
[active] => 1
)
[2] => Array
(
[id] => 1
[title] => 2A
[active] => 1
)
[3] => Array
(
[id] => 1
[title] => B
[active] => 1
)
I have tried several usort methods, but cannot seem to get this to work. I am needing the array sorted so that it will sort by numeric then by alpha numeric like so: A,B,2A,3A.
I am not sure if this would be possible without adding a position field to dictate what order the titles are suppose to be in, or am I missing something here?
You can build a "key" for each item where the digit part is padded on the left with 0s, this way, the sort function can perform a simple string comparison:
$temp = [];
foreach ($arr as $v) {
$key = sscanf($v['title'], '%d%s');
if (empty($key[0])) $key = [ 0, $v['title'] ];
$key = vsprintf("%06d%s", $key);
$temp[$key] = $v;
}
ksort($temp);
$result = array_values($temp);
demo
This technique is called a "Schwartzian Transform".
As #Kargfen said, you can use usort with your custom function. Like this one :
usort($array, function(array $itemA, array $itemB) {
return myCustomCmp($itemA['title'], $itemB['title']);
});
function myCustomCmp($titleA, $titleB) {
$firstLetterA = substr($titleA, 0, 1);
$firstLetterB = substr($titleB, 0, 1);
//Compare letter with letter or number with number -> use classic sort
if((is_numeric($firstLetterA) && is_numeric($firstLetterB)) ||
(!is_numeric($firstLetterA) && !is_numeric($firstLetterB)) ||
($firstLetterA === $firstLetterB)
) {
return strcmp($firstLetterA, $firstLetterB);
}
//Letters first, numbers after
if(! is_numeric($firstLetterA)) {
return -1;
}
return 1;
}
This compare-function is just based on the first letter of your titles, but it can do the job ;-)
You can resolve that problem with help of usort and custom callback:
function customSort($a, $b)
{
if ($a['id'] == $b['id']) {
//if there is no number at the beginning of the title, I add '1' to temporary variable
$aTitle = is_numeric($a['title'][0]) ? $a['title'] : ('1' . $a['title']);
$bTitle = is_numeric($b['title'][0]) ? $b['title'] : ('1' . $b['title']);
if ($aTitle != $bTitle) {
return ($aTitle < $bTitle) ? -1 : 1;
}
return 0;
}
return ($a['id'] < $b['id']) ? -1 : 1;
}
usort($array, "customSort");
At first the function compares 'id' values and then if both items are equal it checks 'title' values.
I want to sort this array by year:
Array
(
[0] => data/pictures/alice/1980
[1] => data/pictures/alice/1985
[2] => data/pictures/bob/1981
[3] => data/pictures/bob/1985
[4] => data/pictures/bob/1987
[5] => data/pictures/bob/1989
)
Expected result:
Array
(
[0] => data/pictures/alice/1980
[1] => data/pictures/bob/1981
[2] => data/pictures/alice/1985
[3] => data/pictures/bob/1985
[4] => data/pictures/bob/1987
[5] => data/pictures/bob/1989
)
I've already tried different sort functions without success.
Example:
asort($paths, SORT_STRING | SORT_FLAG_CASE);
sort($path, SORT_NUMERIC);
Since it's a path just map the array through basename() and then sort based on that:
array_multisort(array_map('basename', $paths), SORT_ASC, $paths);
Try this
function cmp($a, $b) {
// if equal, don't do much
if ($a == $b) {
return 0;
}
$explodedA = explode('/', $a);
$explodedB = explode('/', $b);
$yearPartA = $explodedA[count($explodedA) - 1];
$yearPartB = $explodedB[count($explodedB) - 1];
if ($explodedPartA == $explodedPartB) { // compare full string
return ($a < $b) ? -1 : 1;
}
return ($yearPartA < $yearPartB) ? -1 : 1;
}
// actual sort of the array $path (e.g. the whole point)
usort($path, "cmp");
Consider, however that you'd probably be doing 'explode' several times for each array element and that it might be cheaper to work a bit on the array first. Not sure how big your array is... Do some testing.
$array = ['data/pictures/alice/1980','data/pictures/alice/1985','data/pictures/bob/1981','data/pictures/bob/1985','data/pictures/bob/1987','data/pictures/bob/1989'];
uasort($array, function($a,$b) {
$y1 = array_pop(explode('/', $a));
$y2 = array_pop(explode('/', $b));
if($y1===$y2) {
// if year the same use other criteria
if($a===$b) {
return 0;
}
return $a>$b?-1:1;
};
return $y1>$y2?-1:1;
});
Use usort and in the custom function explode the strings by "/" and compare the last parts of the arrays.
I have array:
$array = array(array('2012-12-12', 'vvv'), array('2012-12-14', 'df'),array('2012-12-10', 'vvv'),array('2012-12-11', 'vvv'));
Array
(
[0] => Array
(
[0] => 2012-12-12
[1] => vvv
)
[1] => Array
(
[0] => 2012-12-14
[1] => df
)
[2] => Array
(
[0] => 2012-12-10
[1] => vvv
)
[3] => Array
(
[0] => 2012-12-11
[1] => vvv
)
)
http://codepad.org/gxw2yKMU
is possible to sort this with dates DESC? For this example should be:
$array[1] //2012-12-14
$array[0] //2012-12-12
$array[3] //2012-12-11
$array[2] //2012-12-10
For me the best way is use embedded functions for PHP, but how? :)
You can use usort with a custom function. If you're on PHP < 5.3 you'll need a named function rather than, as I have, an anonymous one.
$array = array(
array('2012-12-12', 'vvv'),
array('2013-12-14', 'df'),
array('2012-12-14', 'df'),
array('2012-12-10', 'vvv'),
array('2012-12-11', 'vvv')
);
usort($array, function($a, $b) {
if ($a[0] == $b[0]) return 0;
return ($a > $b) ? -1 : 1;
});
print_r($array);
You should be able to use usort
usort( $array, 'sortFunction' );
function sortFunction( $a, $b ) {
if( $a[0] == $b[0] )
return 0;
return ( $a[0] > $b[0] ? return -1 : 1 );
}
You can use array_multisort() :
foreach ($array as $key => $row) {
$dates[$key] = $row[0];
}
array_multisort($dates, SORT_DESC, $array);
First, you put out all dates in a new array. Then, array_multisort() will sort the second array ($array) in the same order than the first ($dates)