I have the following array:
Array ( [0] => Array
( [name] => Jonah
[age] => 27 )
[1] => Array
( [name] => Bianca
[age] => 32 )
)
Is it possible to sort the sub-array values in [age] into some sort of order, such as lowest to highest or vice versa?
You can do this using usort:
usort($arr, function($a, $b)
{
return $a['age'] - $b['age']; // sorts lowest to highest
});
Swap $a and $b in the function to reverse the ordering.
I think this should be possible with bool usort ( array &$array , callback $cmp_function )
http://php.net/manual/en/function.usort.php
Just define a callback that sorts by the [age] key of the value.
This will work:
$ages = array();
foreach ($array as $value) {
$ages[] = $value;
}
array_multisort($values, SORT_ASC, $array);
Any way is good, but this is the "PHP way":
array_multisort() can be used to sort several arrays at once, or a multi-dimensional array by one or more dimensions.
Related
Since this question has a long explanation, I'll ask the question, then have the explanation below -- Can you sort a multidimensional array by their internal array key value, or is there a better way to get around sorting key value pairs that will have inevitable duplicates, than just using an array?
I am mostly unfamiliar with using PHP and want to learn how to store data.
The very simple example I made is just two HTML form inputs for a score and a name and a PHP file to handle the input to be stored in a plain .txt file, which was originally written with the pattern
42|John
32|Jane
25|John
I was able to successfully split the data, sort it, add the new inputted values then store it all back in the text file to be displayed somewhere else, using the name as the key and the score as the value.
I did all this only to realize that it would only store sort and display the last value associated with each name (i.e.)
42|John
32|Jane
25|John
would be sorted to
32|Jane
25|John
because you, obviously, can't have two of the same keys in an array, which is something I completely overlooked.
My solution, currently is to have an extra number that is unique to each name/score pair, which I formatted in the text file as
1|42|John
2|32|Jane
3|25|John
I then split them into a multidimensional array using this foreach loop
foreach($arr as $key => $value) {
$lineData = explode("|", $value);
$scores[$lineData[0]] = array($lineData[1] => $lineData[2]);
}
To get this output
Array
(
[1] => Array
(
[42] => John
)
[2] => Array
(
[32] => Jane
)
[3] => Array
(
[25] => John
)
)
which avoids overwriting any duplicate names or scores, but leaves me in a position where I can't (to my knowledge) use arsort() to sort the array in to highest to lowest.
You can use array_multisort for that, in combination with array_column. Because the key values are strings, you need to also convert them to integers, for which you can use array_map("intval", ...):
foreach($arr as $value) {
$result[] = explode("|", $value);
}
array_multisort(array_map("intval", array_column($result, 0)), $result);
After the above code has run, $result will be sorted by the key values:
[
['25', 'John'],
['32', 'Jane'],
['42', 'John']
]
To reverse the order, apply array_reverse to the result.
Alternative
You could also decide to sort the original array without conversion to a 2D array, and sort it with a custom sort callback, using usort and (again) intval:
usort($arr, function ($a, $b) {
return intval($a) - intval($b);
});
Then $arr will be sorted to:
[
'25|John',
'32|Jane',
'42|John'
]
To reverse the order, switch the position of $a and $b in the sort callback function:
return intval($b) - intval($a);
If we make a small change to your foreach iteration like this:
foreach($arr as $key => $value) {
$lineData = explode("|", $value);
$scores[] = array('score' => $lineData[1], 'name' => $lineData[2]);
}
Your array will have:
Array
(
[0] => Array
(
[score] => 42
[name] => John
)
[1] => Array
(
[score] => 32
[name] => Jane
)
[2] => Array
(
[score] => 25
[name] => John
)
)
You can use the uasort function, which takes the array to sort, and an user-defined function to do the sorting. The code would look like this:
function compare($a, $b)
{
if ($b['score'] == $a['score']) {
if ($a['name'] == $b['name']) {
return 0;
} elseif ($a['name'] < $b['name']) {
return -1;
} else {
return 1;
}
} else {
return ($b['score'] - $a['score']);
}
}
print_r($scores);
uasort($scores, 'compare');
print_r($scores);
Which gives the following result:
Array
(
[1] => Array
(
[score] => 32
[name] => Jane
)
[2] => Array
(
[score] => 25
[name] => John
)
[0] => Array
(
[score] => 42
[name] => John
)
)
When you use a user-defined function for the sorting you need to return one of 3 values (0 of the values as equal, -1 if $a < $b, and 1 if $b > $a. In this case we're sorting first by score (descending), then by name (ascending). Since you need to order from highest to lowest score, the comparison is $b against $a, for ascending order is $a against $b. I didn't consider the extra number necessary. If you need it then change this line:
$scores[] = array('score' => $lineData[1], 'name' => $lineData[2]);
To this:
$scores[$lineData[0]] = array('score' => $lineData[1], 'name' => $lineData[2]);
I have an array of range type values 257-1024, 1-256, 1025-2056. All these values are dynamically generated and positioned randomed. Before making an output I have to sort them in a numeric ASC order. Using sort or natsort function is giving the output as 1-256,1025-2056, 257-1024 as php recognise it as string. Is there a built in function with which this can be sorted/arranged in numeric range order i.e 1-256, 257-1024, 1025-2056
You can use natsort() function here.
$array = array("257-1024", "1-256", "1025-2056");
$a = natsort($array);
echo "<pre>";
print_r($array);
echo "</pre>";
Output:
Array
(
[1] => 1-256
[0] => 257-1024
[2] => 1025-2056
)
Hope this helps.
You can do like below using usort().
$array = ['257-1024', '1025-2056', '1-256'];
usort($array, function($a, $b){
return ((int)explode('-', $a)[1] < (int)explode('-', $b)[0]) ? -1 : 1;
});
print_r($array);
Output is below.
Array
(
[0] => 1-256
[1] => 257-1024
[2] => 1025-2056
)
I know this question has been asked many times but I have yet to see an array built like this. I have tried some of the numerous examples I have found but none seem to do the trick.
I am editing a PHP program that creates a dropdown list of UPS rates. The functions in this program create an array that is structured like this. I'd like to be able to sort this array on [price].
Array
(
[price] => Array
(
[0] => 617.75
[1] => 632.97
[2] => 782.77
[3] => 597.93
[4] => 337.00
)
[option_value] => Array
(
[0] => 07
[1] => 08
[2] => 54
[3] => 65
[4] => 11
)
[option_name] => Array
(
[0] => WorldWide Express
[1] => WorldWide Expedited
[2] => WorldWide Express Plus
[3] => International Saver
[4] => International Standard
)
)
For ascending, I would try:
array_multisort($array['price'], SORT_ASC, $array['option_value'], $array['option_name']);
To go along with the other answer to restructure the array:
foreach($array['price'] as $key => $value) {
$result[] = array('price'=>$array['price'][$key],
'option_value'=>$array['option_value'][$key],
'option_name'=>$array['option_name'][$key]);
}
array_multisort(array_column($result, 'price'), SORT_ASC, $result);
First, I'd refactor the dataset into something sensible:
$i = 0;
$result = [];
while($i < count($source['price']) ) {
$result[$i] = [
'price' => $source['price'][$i],
'option_value' => $source['option_value'][$i],
'option_name' => $source['option_name'][$i]
];
++$i;
}
Then, sort the result using usort:
function sort_by_price($a, $b) {
if ($a['price'] == $b['price']) {
return 0;
}
return ($a['price'] < $b['price']) ? -1 : 1;
}
usort($result, "sort_by_price");
what will i do is this
$price = $array['price'];
asort($price);
foreach($price as $key=>$val){
echo $val.'='.$array['option_value'][$key].'='.$array['option_name'][$key].'<br />';
}
i used asort to sort the value ASC and to preserve the array key. you can also use arsort to sort array value DESC.
asort: http://php.net/manual/en/function.asort.php
arsort: http://php.net/manual/en/function.arsort.php
<?php
$ar = array(
array("10", 11, 100, 100, "a"),
array( 1, 2, "2", 3, 1)
);
array_multisort($ar[0], SORT_ASC, SORT_STRING,
$ar[1], SORT_NUMERIC, SORT_DESC);
var_dump($ar);
?>
array1_sort_order
The order used to sort the previous array argument. Either SORT_ASC to sort ascendingly or SORT_DESC to sort descendingly.
This argument can be swapped with array1_sort_flags or omitted entirely, in which case SORT_ASC is assumed.
Sorting type flags:
SORT_REGULAR - compare items normally (don't change types)
SORT_NUMERIC - compare items numerically
SORT_STRING - compare items as strings
SORT_LOCALE_STRING - compare items as strings, based on the current locale. It uses the locale, which can be changed using setlocale()
SORT_NATURAL - compare items as strings using "natural ordering" like natsort()
SORT_FLAG_CASE - can be combined (bitwise OR) with SORT_STRING or SORT_NATURAL to sort strings case-insensitively
SRC: Example #2 Sorting multi-dimensional array
In the following array, I want to change the key order from high to low (so for example the year 2014 data appears first).
print_r($array);
Output:
Array
(
[0] => Array
(
[year] => 2013
[name] => xx
)
[1] => Array
(
[year] => 2014
[name] => xx
)
)
I have tried using rsort, but it returns only "1".
$array = rsort($array);
print_r($array); //1
var_dump($array); //bool(true).
rsort() will only work on single-dimensional arrays. You have a 2-dimensional array, so you will need to use a different function such as usort(), which lets you use user-defined comparison function for sorting:
usort($data, function ($a, $b) {
return $a['year'] < $b['year'];
});
Output:
Array
(
[0] => Array
(
[year] => 2014
[name] => xx
)
[1] => Array
(
[year] => 2013
[name] => xx
)
)
Working demo
change
$array = rsort($array);
print_r($array);
to
rsort($array);
print_r($array);
rsort has return value of boolean, so just simple use it like this:
rsort($array);
And also, rsort is sorting array values in reverse order, not array keys, check the documentation:
http://php.net/manual/en/function.rsort.php
So in reverse order simply just use krsort - Sort an array by key in reverse order:
http://php.net/manual/en/function.krsort.php
So your code:
krsort($array);
usort($array, function($item1, $item2){
if ($item1->year > $item2->year ) return true;
else return false;
})
That´s if you wanted to order by year, if you want to order by keys uksort could be used instead
I've got an multi-dimensional array at the moment and want to remove the second-level of arrays and have the value of that second level as the new index value on the parent array. My current array is:
Array ( [0] => Array ( [connectee] => 1 ) [1] => Array ( [connectee] => 6 ) )
And want from that:
Array ( [0] => 1, [1] => 6 )
I was poking around the usort function but couldn't get it to work (where $current_connections is my array as above:
function cmp($a, $b) {
return strcmp($a["connectee"], $b["connectee"]);
}
$current_connections = usort($current_connections, "cmp");
The key doesn't need to be maintained (should be destroyed in the process).
foreach ($array as &$value) {
$value = $value['connectee'];
}
Note: Please note that the question statement is very confusing and contradicting, but this answer is based upon your statement for expected output
Array ( [0] => 1, [1] => 6 )
You could do
<?php
$values=array();
$values[0]=array("connectee"=>1);
$values[1]=array("connectee"=>6);
foreach($values as $index=>$value)
{
$values[$index]=$value["connectee"];
}
print_r($values);
?>