php sorting an array based on value - php

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");

Related

How can I call particular array value of array in php?

I'm getting below output as an array.
$array =
Array
(
[12] => Array
(
[1] => Array
(
[14] => Array
(
[0] => Array
(
[name] => Avaya Implementation Services
[service_id] => 14
[ser_type_id] => 1
[service_desc] =>Avaya Implementation Servic
)
)
)
)
);
I want to print only service_desc array value. and I don't want call like $array[12][1][14][0]['service_desc'];
How can I call particular service_desc array value of the array?
As you mentioned that you don't want to call it as $array[12][1][14][0]['service_desc'] you can use extract function which will create variables from your array,
extract($array[12][1][14][0]);
echo $service_desc;
And then you can use your particular key such as service_desc as variable.
You can try this function: (Please optimize as per your requirements)
$arr ="<YOUR ARRAY>";
$val = "service_desc";
echo removekey($arr, $val);
function removekey($arr, $val) {
$return = array();
foreach ($arr as $k => $v) {
if (is_array($v) && $k !== $val) {
removekey($v, $val);
continue;
}
if ($k == $val) {
echo ($arr[$k]);
die;
}
$return[$k] = $v;
}
return $return;
}
You can use array_walk_rescursive to frame a single dimensional array of matching keys:
DEMO
<?php
$array[12][1][14][0]['service_desc'] = 'Avaya Implementation Servic';
$array[12][1][14][0]['service'] = 'dsfasf';
$array[12][1][114][0]['service_desc'] = 'Avaya Implementation Servicasdfdsf';
$searchKey = 'service_desc';
$desiredValues = [];
array_walk_recursive($array, function ($v, $k) use ($searchKey, &$desiredValues) {
if ($k === $searchKey) {
$desiredValues[] = $v;
}
});
print_r($desiredValues);
So this will yield:
Array
(
[0] => Avaya Implementation Servic
[1] => Avaya Implementation Servicasdfdsf
)
You might use the array_walk_recursive function.
array_walk_recursive($array, function ($val, $key) {
if ($key == 'service_desc') print_r($val);
} );
Instead of the print_r statement, you can collect your data into another structure, which you convey using the use statement, or with the $userdata additional parameter (see http://www.php.net/manual/en/function.array-walk-recursive.php ).
$results = array();
array_walk_recursive($array, function ($val, $key) use (&$results) {
if ($key == 'service_desc') {
$results []= $val;
}
} );
Pay extra care to the & in front of the use (&$results) otherwise your array of results will be considered immutable inside the callback (i.e. all changes discarded).
Convert multidimensional array to single array using iterator_to_array
REF: http://php.net/manual/en/function.iterator-to-array.php
$service_desc= iterator_to_array(new RecursiveIteratorIterator(new RecursiveArrayIterator($your_array)), 0);
print_r($service_desc);
Result:
Array
(
[name] => Avaya Implementation Services
[service_id] => 14
[ser_type_id] => 1
[service_desc] =>Avaya Implementation Servic
)

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;
}
});

Sort array by key value

So I have this array.
Array
(
[0] => Array
(
[key_1] => something
[type] => first_type
)
[1] => Array
(
[key_1] => something_else
[type] => first_type
)
[2] => Array
(
[key_1] => something_else_3
[type] => second_type
)
[3] => Array
(
[key_1] => something_else_4
[type] => second_type
)
)
I have to sort by type value in a pattern like this:
first_type
second_type
first_type
second_type
My questions is, how can I do this?
Thanks a lot!
You need to use usort with a custom comparison function that compares the key_1 sub-keys of each item (you can use strcmp to do this conveniently). Assuming you do not want to change the structure of the resulting array, it would look something like this:
$arr = /* your array */
usort($arr, function($a, $b) { return strcmp($a['key_1'], $b['key_1']); });
So here's how I got it to work:
function filter_by_value($array, $index, $value) {
if(is_array($array) && count($array) > 0) {
foreach(array_keys($array) as $key){
$temp[$key] = $array[$key][$index];
if ($temp[$key] == $value){
$newarray[$key] = $array[$key];
}
}
}
return $newarray;
}
$array = /* array here */
$type1 = array_values(filter_by_value($array, 'type', '1'));
$type2 = array_values(filter_by_value($array, 'type', '2'));
$i = 1; $x = 1; $y = 1;
$sorted = array();
foreach ($array as $a) {
if ($i % 2) {
$sorted[$i-1] = $type1[$x-1];
$x++;
} else {
$sorted[$i-1] = $type2[$y-1];
$y++;
}
$i++;
}
Found filter_by_value() on php.net but I don't remember where so, that's not made by me.
Maybe this is not the best solution but it works pretty fine.
If sort() and its relevant alternatives don't work you will have to use usort() or uasort() with a custom function to sort this array.

Sorting multi-dimensional arrays [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 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'));

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']);
});

Categories