Sorting multi-dimensional arrays [duplicate] - php

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 8 years ago.
I have an array like this:
Array (
[0] => Array (
[tag] => /nn
[count] => 55
)
[1] => Array (
[tag] => /vb
[count] => 7
)
)
and I want to sort it. In this example it's already like I want it to be. Sorted by count. What if it was reverse ordered? What function is there to sort it?
Thanks a lot.

Check this code
function aasort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $va) {
$sorter[$ii]=$va[$key];
}
asort($sorter);
foreach ($sorter as $ii => $va) {
$ret[$ii]=$array[$ii];
}
$array=$ret;
}
aasort($your_array,"order");
Or
I usually use usort, and pass my own comparison function. In this case, it is very simple:
function sortByOrder($a, $b) {
return $a['order'] - $b['order'];
}
usort($myArray, 'sortByOrder');
Hope you can find your answer. Mark my answer and point me up, thanks.

$count = array();
// Obtain a list of columns
foreach ($array as $key => $row) {
$count[$key] = $row['count'];
}
//sort by count descending
array_multisort($count, SORT_DESC, $array);
DOC

Use usort() like this:
usort( $array, function( $a, $b ) {
if ( $a['count'] == $b['count'] )
return 0;
return ( $a['count'] > $b['count'] ? -1 : 1 );
}
Reverse the > if you want it to reverse the order.

I 've written a function here that allows you to select which key you want to sort with. You can even specify multiple keys for secondary, tertiary, etc sort.
With this make_comparer function, you would sort like this:
uasort($array, make_comparer('count'));

Related

php sorting an array based on value

I have a very big array. Arrays within arrays. Below is a small portion of it;
[lta/] => Array
(
[2012-12-31/] => Array
(
[0] => 31_december_2012.pdf
[1] => 31_december_2012.xls
[2] => key_points.html
)
)
What I need to do, is get the "key_points.html" value to always start at the top of it's array. Example;
[2012-12-31/] => Array
(
[2] => key_points.html
[0] => 31_december_2012.pdf
[1] => 31_december_2012.xls
)
)
I cannot do a simple asort because I never know at which point "key_points.html" is going to appear in the array.
I tried to rename the values "key_points.html" with a view to sorting it and then un-renaming it after;
foreach($the_array as $array_object => $array_item)
{
if($array_item == "key_points.html") {$array_item = "0001_key_points.html";}
}
But that literally seemed to have no effect! it didn't even rename my value. I also tried the same thing with string replace;
$the_array = str_replace("key_points.html", "0001_key_points.html", $the_array);
Is there a function perhaps that allows you to specify a string, and move that to the top of each array each time if it finds it??
Use uasort to specify a custom comparator callback:
uasort($array, function($a, $b) {
if($a == 'key_points.html') return -1; // Smaller than all
if($b == 'key_points.html') return 1; // Larger than all
return ($a < $b) ? -1 : 1; // Default sorting
});
Syntax is assuming an up to date PHP (5.3+) with support for anonymous functions.
Use custom function
function customSort (&$array, $key) {
$sorter=array();
$ret=array();
reset($array);
foreach ($array as $ii => $val) {
$sorter[$ii]=$va[$key];
}
asort($sorter);
foreach ($sorter as $ii => $val) {
$ret[$ii]=$array[$ii];
}
$array=$ret;
}
customSort($your_array,"2");

How to arrange multiple arrays by a specific field

I have an array that has multiple arrays inside it. I am trying to arrange those arrays from the amount of greatest to least new_sales. Here is the example of the array which goes on for about 40 arrays:
Array
(
[0] => Array
(
[Tech] => Array
(
[first_name] => Anthony
[last_name] => Bisignano
)
[0] => Array
(
[new_sales] => 21
[upgrades] => 2
)
)
[1] => Array
(
[Tech] => Array
(
[first_name] => Arnold
[last_name] => Ybanez
)
[0] => Array
(
[new_sales] => 5
[upgrades] => 0
)
)
The function I am trying to use is the following:
function aasort (&$techs, $key) {
$sorter=array();
$ret=array();
reset($techs);
foreach ($techs as $ii => $va) {
$sorter[$ii]=$va[$key];
}
asort($sorter);
foreach ($sorter as $ii => $va) {
$ret[$ii]=$techs[$ii];
}
$techs=$ret;
}
aasort($test,"new_sales");
AM I using this function wrong or is there another approach I should be taking?
There are sorting functions in PHP that support user-defined comparison methods. Code like this should help you get started with that.
function cmp($a, $b)
{
if ($a[0]['new_sales'] == $b[0]['new_sales']) {
return 0;
}
return ($a[0]['new_sales'] < $b[0]['new_sales']);
}
usort($data, "cmp");
In this case you probably want to use usort() such that you can define your sorting logic.
So something like this:
usort($array, function($a, $b) {
if ($a[0]['new_sales'] > $b[0]['new_sales']) {
return -1; // note we use -1 here because we want a reverse sort
} else if ($a[0]['new_sales'] < $b[0]['new_sales']) {
return 1;
} else {
return 0;
}
});

How to sort a subarrays by the leading integers of a specific column value?

The array below should be sorted by the first number of cat_url_title in an ascending direction.
Array
(
[0] => Array
(
[cat_id] => 14
[parent_id] => 2
[cat_url_title] => 20-a-43m
)
[1] => Array
(
[cat_id] => 13
[parent_id] => 2
[cat_url_title] => 16-a-20m
)
[2] => Array
(
[cat_id] => 12
[parent_id] => 2
cat_url_title] => 12-a-16m
)
)
//get the first number
foreach( $arr as $k => $v )
{
$segs = explode("-",$v['cat_url_title']);
$nbr = $segs[0]; //this will be 20, 16 or 12
}
The subarray with the cat_url_title value starting with 12 should become $arr[0], 16 should remain as $arr[1], and 20 should move to $arr[2].
How can I achieve this?
you're on a good way, after getting the first numbers create a new array containing the number as a key and the contents of the array as value:
$newArray = array();
foreach($arr as $k => $v)
{
$segs = explode("-", $v['cat_url_title']);
$newArray[ $segs[0] ] = $v;
}
ksort($newArray);
print_r($newArray);
that should work.
usort()
See the usort() php function.
Interesting page about array sorting functions in php: http://us.php.net/manual/en/array.sorting.php
One-liner:
array_multisort(array_map('end', $array), SORT_NUMERIC, $array);
Assuming:
$array = array (
0 => array (
'cat_id' => 14,
'parent_id' => 2,
'cat_url_title' => '20-a-43m'
),
1 => array (
'cat_id' => 13,
'parent_id' => 2,
'cat_url_title' => '16-a-20m'
),
2 => array (
'cat_id' => 12,
'parent_id' => 2,
'cat_url_title' => '12-a-16m'
)
);
Here is a function I use to sort arrays:
function array_sort($array, $on, $order='SORT_DESC' /*or SORT_ASC*/ )
{
$new_array = array();
$sortable_array = array();
if (count($array) > 0) {
foreach ($array as $k => $v) {
if (is_array($v)) {
foreach ($v as $k2 => $v2) {
if ($k2 == $on) {
$sortable_array[$k] = $v2;
}
}
} else {
$sortable_array[$k] = $v;
}
}
switch($order)
{
case 'SORT_ASC':
asort($sortable_array);
break;
case 'SORT_DESC':
arsort($sortable_array);
break;
}
foreach($sortable_array as $k => $v) {
$new_array[] = $array[$k];
}
}
return $new_array;
}
Usage:
array_sort($restaurants_top, "score", 'SORT_DESC');
$restaurants_top = a list of restaurants
"score" = an array key
SORT_DESC = direction of sorting
Tomasz's suggestion of array_multisort() is a clever, declarative, and concise technique that has been available in php versions for many years. I'd likely use array_multisort() if this task was in my project.
I might suggest, for project stability (in case the data structure is extended/changed), to explicitly name the column to be sorted by. The following snippet also avoids making iterated end() calls.
array_multisort(array_column($array, 'cat_url_title'), SORT_NUMERIC, $array);
I'll show a couple of modern alternatives as an academic exercise.
From PHP7, the spaceship operator also provides a concise syntax. To isolate the numeric substring before the first hyphen cast the strings as integers.
usort($array, function($a, $b) {
return (int)$a['cat_url_title'] <=> (int)$b['cat_url_title'];
});
From PHP7.4, arrow function syntax makes a usort() call more concise, but arguably more cryptic to read if you are not used to the syntax.
usort($array, fn($a, $b) => (int)$a['cat_url_title'] <=> (int)$b['cat_url_title']);
As with nearly all of my php posts, here is an online demo to prove that all of my snippets function as intended.
Snippets on this page that iterate the input array multiple times should be avoided.
p.s. if you wish to sort the cat_url_title values on the four numeric/alphabetic substrings, you can write these substrings as arrays on each side of the spaceship operator and it will evaluate the substrings from left to right to determine the sorting outcomes.
Code: (Demo)
usort($array, function($a, $b) {
return (preg_match_all('~[a-z]+|\d+~', $a['cat_url_title'], $out) ? $out[0] : ['','','',''])
<=>
(preg_match_all('~[a-z]+|\d+~', $b['cat_url_title'], $out) ? $out[0] : ['','','','']);
});
p.p.s. This is may a good case for version_compare(). Unfortunately, it is not reliable for the strings in my test battery. Take note of the final position of the 16-a-20n subarray in this demo. I believe that the function is ignoring the final letter because the evaluation is 0 between 16-a-20m and 16-a-20n.
As for your sample strings with consistent a and m substring positions, it works perfectly to naturally sort.
Code: (Demo)
usort($array, function($a, $b) {
return version_compare($a['cat_url_title'], $b['cat_url_title']);
});

How do i sort multidimension array in PHP? [duplicate]

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 5 months ago.
I have array like
Array (
[608665839] => Array ( [score] => 2 )
[1756044141] => Array ( [score] => 5 )
[523536777] => Array ( [score] => 2 )
)
and I want to sore this array by score. How can I do?
I would use uasort
I think [uasort()]1 function is helpful for sorting this array()
If multiple array then use array_[multisort()]2 functions
From PHP.net:
<?php
function order_array_num ($array, $key, $order = "ASC")
{
$tmp = array();
foreach($array as $akey => $array2)
{
$tmp[$akey] = $array2[$key];
}
if($order == "DESC")
{arsort($tmp , SORT_NUMERIC );}
else
{asort($tmp , SORT_NUMERIC );}
$tmp2 = array();
foreach($tmp as $key => $value)
{
$tmp2[$key] = $array[$key];
}
return $tmp2;
}
?>
$order = "ASC" will sort the array in an ascending order while $order = "DESC" will sort the array in a descending order.
Hope this helps.

Sorting an associative array in PHP [duplicate]

This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 8 years ago.
I have an array in this format:
Array
(
[0] => Array
(
[text] => tests
[language] =>
[advertiserCompetitionScale] => 5
[avgSearchVolume] => 7480000
[lastMonthSearchVolume] => 9140000
)
[1] => Array
(
[text] => personality tests
[language] =>
[advertiserCompetitionScale] => 5
[avgSearchVolume] => 165000
[lastMonthSearchVolume] => 201000
)
[2] => Array
(
[text] => online tests
[language] =>
[advertiserCompetitionScale] => 5
[avgSearchVolume] => 246000
[lastMonthSearchVolume] => 301000
)
)
How can I sort an array in that format, in the descending order of the avgSearchVolume field? Is there a built in function for this?
Use usort and supply your own function to do the ordering, e.g.
function cmp($a, $b)
{
return $b['avgSearchVolume'] - $a['avgSearchVolume'];
}
usort($array, "cmp");
Until PHP 5.3 this is the best function for sorting based on subkeys without making a new function for each key.
function sortBySubkey(&$array, $subkey, $sortType = SORT_ASC) {
foreach ($array as $subarray) {
$keys[] = $subarray[$subkey];
}
array_multisort($keys, $sortType, $array);
}
sortBySubkey($arr, 'avgSearchVolume');
With PHP 5.3 you can make something like this, same function call as now.
function getSortVariable($sortType = SORT_ASC) {
switch($sortType) {
case SORT_ASC:
return function ($a, $b) use ($subkey) { return strcmp($a[$subkey], $b[$subkey]); };
}
}
function sortBySubkey(&$array, $subkey, $sortType = SORT_ASC) {
$sortFunction = getSortVariable($sortType);
usort($array, $sortFunction($subkey));
}
You'll have to use a custom callback function together with usort().
function cmp($a, $b)
{
if ($a['avgSearchVolume'] == $b['avgSearchVolume']) {
return 0;
}
return ($a['avgSearchVolume'] > $b['avgSearchVolume']) ? -1 : 1;
}
usort($array, 'cmp');
function querySort ($first_Array,$second_Array) {
return strcasecmp($first_Array['name'],$second_Array['name']);
}
echo '<pre>';
usort($main, 'querySort');
print_r($main);
die;
Here is another solution, You can add multiple options for sorting(See the commented section of the code)
<?php
$arr=Array(
Array("text" => "tests","language" =>"","advertiserCompetitionScale" => 5,"avgSearchVolume" => 7480000,"lastMonthSearchVolume" => 9140000),
Array("text" => "personality tests","language" =>"","advertiserCompetitionScale" => 5,"avgSearchVolume" => 165000,"lastMonthSearchVolume"=>201000),
Array("text" => "online tests","language" =>"","advertiserCompetitionScale" => 5,"avgSearchVolume" => 246000,"lastMonthSearchVolume" =>301000)
);
$sort = array();
foreach($arr as $k=>$v) {
$sort['avgSearchVolume'][$k] = $v['avgSearchVolume'];
//$sort['text'][$k] = $v['text'];
}
array_multisort($sort['avgSearchVolume'], SORT_DESC, $arr);
//array_multisort($sort['avgSearchVolume'], SORT_DESC, $sort['text'], SORT_ASC,$arr);
echo "<pre>";
print_r($arr);
?>
REF: http://php.net/manual/en/function.array-multisort.php

Categories