I have an php array like below:
Array (
[0] => Array ( [value] => 5 [label] => Akon )
[1] => Array ( [value] => 6 [label] => Angel )
[2] => Array ( [value] => 7 [label] => Britny )
[3] => Array ( [value] => 9 [label] => Mark Anthony )
[4] => Array ( [value] => 8 [label] => Michel )
[5] => Array ( [value] => 4 [label] => Shaggy )
[6] => Array ( [value] => 3 [label] => Smith )
)
I need this array sort by specific letter. For example, if I sort by this "M" letter array should look like below.
Array (
[3] => Array ( [value] => 9 [label] => Mark Anthony )
[4] => Array ( [value] => 8 [label] => Michel )
[6] => Array ( [value] => 3 [label] => Smith )
[0] => Array ( [value] => 5 [label] => Akon )
[1] => Array ( [value] => 6 [label] => Angel )
[2] => Array ( [value] => 7 [label] => Britny )
[5] => Array ( [value] => 4 [label] => Shaggy )
)
The begging letter should comes to first of array.(here begin with m)
I greatly appreciated your any kind of help. Thank you very much...
Your comparison logic is going to be like this:
if two strings A and B start with the same letter, compare them as usual
if A starts with 'M', A wins
if B starts with 'M', B wins
otherwise, compare as usual
in code
$strings = array('Foo', 'Moo', 'Xuux', 'Me', 'Blah', 'Ma');
$letter = 'M';
usort($strings, function($a, $b) use($letter) {
if($a[0] != $b[0]) {
if($a[0] == $letter) return -1;
if($b[0] == $letter) return +1;
}
return strcmp($a, $b);
});
print_r($strings);
class Cmp {
public $letter;
function __construct( $letter ) { $this->letter = $letter; }
function doCmp( $a, $b ) {
if( $a['label'][0] == $this->letter ) {
if( $b['label'][0] != $this->letter ) return -1;
} else {
if( $b['label'][0] == $this->letter ) return 1;
}
return $a['label'] > $b['label'] ? 1 : -1;
}
}
usort( $arr, array( new Cmp( 'M' ), 'doCmp' ) );
$strings = array (
array ( 'value' => 5, 'label' => 'Akon' ),
array ( 'value' => 6, 'label' => 'Angel' ),
array ( 'value' => 7, 'label' => 'Britny' ),
array ( 'value' => 9, 'label' => 'Mark Anthony' ) ,
array ( 'value' => 8, 'label' => 'Michel' ) ,
array ( 'value' => 4, 'label' => 'Shaggy' ) ,
array ( 'value' => 3, 'label' => 'Smith' )
) ;
var_dump($strings);
$letter = 'm';
usort ($strings, function ($left, $right) {
return ((($posLeft = strpos(strtolower($left['label']), 'm')) === false)
? PHP_INT_MAX
: $posLeft)
- ((($posRight = strpos(strtolower($right['label']), 'm')) === false)
? PHP_INT_MAX
: $posRight);
});
var_dump($strings);
Just compares the position of the letter within the two strings. If the letter is not within one of the strings (strpos() returns false), it assumes an "infinite" index (PHP_INT_MAX),
this is an example i found on php.net that could help you and maintain the index : http://www.php.net/manual/en/function.sort.php#99419
Sort the data by the value based on the comparison reflecting the letter (Demo):
<?php
# the data
$data = array(
0 => array(
'value' => 5,
'label' => 'Akon',
),
1 => array(
'value' => 6,
'label' => 'Angel',
),
2 => array(
'value' => 7,
'label' => 'Britny',
),
3 => array(
'value' => 9,
'label' => 'Mark Anthony',
),
4 => array(
'value' => 8,
'label' => 'Michel',
),
5 => array(
'value' => 4,
'label' => 'Shaggy',
),
6 => array(
'value' => 3,
'label' => 'Smith',
),
);
# the letter
$letter = 'M';
# the value to compare against
$value = function(array $a)
{
$key = 'label';
if (!array_key_exists($key, $a))
{
throw new InvalidArgumentException(sprintf('Key "%s" missing.', $key));
}
return $a[$key];
};
# the comparison
$compare = function($a, $b) use ($letter, $value)
{
$a = $value($a);
$b = $value($b);
if($a[0] != $b[0]) {
if($a[0] === $letter) return -1;
if($b[0] === $letter) return +1;
}
return strcmp($a, $b);
};
# the sort
$sort = function() use ($data, $compare)
{
$r = uasort($data, $compare);
if (!$r)
{
throw new RuntimeException('Sort failed.');
}
return $data;
};
print_r($sort());
Use usort to sort by a function. The function can contain any logic you want to put in, as long as the return value indicates sort order (see link for details).
Related
I have an array of subarrays in the following format:
[
'a' => ['id' => 20, 'name' => 'chimpanzee'],
'b' => ['id' => 40, 'name' => 'meeting'],
'c' => ['id' => 20, 'name' => 'dynasty'],
'd' => ['id' => 50, 'name' => 'chocolate'],
'e' => ['id' => 10, 'name' => 'bananas'],
'f' => ['id' => 50, 'name' => 'fantasy'],
'g' => ['id' => 50, 'name' => 'football']
]
And I would like to group it into a new array based on the id field in each subarray.
array
(
10 => array
(
e => array ( id = 10, name = bananas )
)
20 => array
(
a => array ( id = 20, name = chimpanzee )
c => array ( id = 20, name = dynasty )
)
40 => array
(
b => array ( id = 40, name = meeting )
)
50 => array
(
d => array ( id = 50, name = chocolate )
f => array ( id = 50, name = fantasy )
g => array ( id = 50, name = football )
)
)
$arr = array();
foreach ($old_arr as $key => $item) {
$arr[$item['id']][$key] = $item;
}
ksort($arr, SORT_NUMERIC);
foreach($array as $key => $value){
$newarray[$value['id']][$key] = $value;
}
var_dump($newarray);
piece of cake ;)
The following code adapts #Tim Cooper’s code to mitigate Undefined index: id errors in the event that one of the inner arrays doesn’t contain an id:
$arr = array();
foreach($old_arr as $key => $item)
{
if(array_key_exists('id', $item))
$arr[$item['id']][$key] = $item;
}
ksort($arr, SORT_NUMERIC);
However, it will drop inner arrays without an id.
E.g.
$old_arr = array(
'a' => array ( 'id' => 20, 'name' => 'chimpanzee' ),
'b' => array ( 'id' => 40, 'name' => 'meeting' ),
'c' => array ( 'id' => 20, 'name' => 'dynasty' ),
'd' => array ( 'id' => 50, 'name' => 'chocolate' ),
'e' => array ( 'id' => 10, 'name' => 'bananas' ),
'f' => array ( 'id' => 50, 'name' => 'fantasy' ),
'g' => array ( 'id' => 50, 'name' => 'football' ),
'h' => array ( 'name' => 'bob' )
);
will drop the 'h' array completely.
You can also use Arrays::groupBy() from ouzo-goodies:
$groupBy = Arrays::groupBy($array, Functions::extract()->id);
print_r($groupBy);
And result:
Array
(
[20] => Array
(
[0] => Array
(
[id] => 20
[name] => chimpanzee
)
[1] => Array
(
[id] => 20
[name] => dynasty
)
)
[40] => Array
(
[0] => Array
(
[id] => 40
[name] => meeting
)
)
[50] => Array
(
[0] => Array
(
[id] => 50
[name] => chocolate
)
[1] => Array
(
[id] => 50
[name] => fantasy
)
[2] => Array
(
[id] => 50
[name] => football
)
)
[10] => Array
(
[0] => Array
(
[id] => 10
[name] => bananas
)
)
)
And here are the docs for Arrays and Functions.
Here is a function that will take an array as the first argument and a criteria (a string or callback function) as the second argument. The function returns a new array that groups the array as asked for.
/**
* Group items from an array together by some criteria or value.
*
* #param $arr array The array to group items from
* #param $criteria string|callable The key to group by or a function the returns a key to group by.
* #return array
*
*/
function groupBy($arr, $criteria): array
{
return array_reduce($arr, function($accumulator, $item) use ($criteria) {
$key = (is_callable($criteria)) ? $criteria($item) : $item[$criteria];
if (!array_key_exists($key, $accumulator)) {
$accumulator[$key] = [];
}
array_push($accumulator[$key], $item);
return $accumulator;
}, []);
}
Here is the given array:
$arr = array(
'a' => array ( 'id' => 20, 'name' => 'chimpanzee' ),
'b' => array ( 'id' => 40, 'name' => 'meeting' ),
'c' => array ( 'id' => 20, 'name' => 'dynasty' ),
'd' => array ( 'id' => 50, 'name' => 'chocolate' ),
'e' => array ( 'id' => 10, 'name' => 'bananas' ),
'f' => array ( 'id' => 50, 'name' => 'fantasy' ),
'g' => array ( 'id' => 50, 'name' => 'football' )
);
And examples using the function with a string and a callback function:
$q = groupBy($arr, 'id');
print_r($q);
$r = groupBy($arr, function($item) {
return $item['id'];
});
print_r($r);
The results are the same in both examples:
Array
(
[20] => Array
(
[0] => Array
(
[id] => 20
[name] => chimpanzee
)
[1] => Array
(
[id] => 20
[name] => dynasty
)
)
[40] => Array
(
[0] => Array
(
[id] => 40
[name] => meeting
)
)
[50] => Array
(
[0] => Array
(
[id] => 50
[name] => chocolate
)
[1] => Array
(
[id] => 50
[name] => fantasy
)
[2] => Array
(
[id] => 50
[name] => football
)
)
[10] => Array
(
[0] => Array
(
[id] => 10
[name] => bananas
)
)
)
Passing the callback is overkill in the example above, but using the callback finds its use when you pass in an array of objects, a multidimensional array, or have some arbitrary thing you want to group by.
Maybe it's worth to mention that you can also use php array_reduce function
$items = [
['id' => 20, 'name' => 'chimpanzee'],
['id' => 40, 'name' => 'meeting'],
['id' => 20, 'name' => 'dynasty'],
['id' => 50, 'name' => 'chocolate'],
['id' => 10, 'name' => 'bananas'],
['id' => 50, 'name' => 'fantasy'],
['id' => 50, 'name' => 'football'],
];
// Grouping
$groupedItems = array_reduce($items, function ($carry, $item) {
$carry[$item['id']][] = $item;
return $carry;
}, []);
// Sorting
ksort($groupedItems, SORT_NUMERIC);
print_r($groupedItems);
https://www.php.net/manual/en/function.array-reduce.php
Because of how PHP's sorting algorithm treats multidimensional arrays -- it sorts by size, then compares elements one at a time, you can actually use a key-preserving sort on the input BEFORE restructuring. In functional style programming, this means that you don't need to declare the result array as a variable.
Code: (Demo)
asort($array);
var_export(
array_reduce(
array_keys($array),
function($result, $k) use ($array) {
$result[$array[$k]['id']][$k] = $array[$k];
return $result;
}
)
);
I must say that functional programming is not very attractive for this task because the first level keys must be preserved.
Although array_walk() is more succinct, it still requires the result array to be passed into the closure as a reference variable. (Demo)
asort($array);
$result = [];
array_walk(
$array,
function($row, $k) use (&$result) {
$result[$row['id']][$k] = $row;
}
);
var_export($result);
I'd probably recommend a classic loop for this task. The only thing the loop needs to do is rearrange the first and second level keys. (Demo)
asort($array);
$result = [];
foreach ($array as $k => $row) {
$result[$row['id']][$k] = $row;
}
var_export($result);
To be completely honest, I expect that ksort() will be more efficient than pre-loop sorting, but I wanted to a viable alternative.
This question already has answers here:
Put multiple arrays in one large associative array
(2 answers)
Closed 2 years ago.
I am having two arrays with same keys from two different queries.
First query result:
Array
(
[0] => Array
(
[Contribution] => 1000.00
[P_Name] => A
)
[1] => Array
(
[Contribution] => 1500.00
[P_Name] => B
)
)
Second query result:
Array
(
[0] => Array
(
[Contribution] => 100.00
[P_Name] => A
)
[1] => Array
(
[Contribution] => 200.00
[P_Name] => B
)
)
The first array may be empty and/or the second may be empty.
I want to get the create a new array that finds the sum of Contribution values where P_Name values match, like this:
Array
(
[0] => Array
(
[Contribution] => 1100.00
[P_Name] => A
)
[1] => Array
(
[Contribution] => 1700.00
[P_Name] => B
)
)
I have tried array_merge():
$result1= $this->model1->getOthersTotal($date);
$result2=$this->model1->getMiscTotal($date);
$merged_result = array_merge( $result1, $result2 );
$merged_result contains:
Array (
[0] => Array (
[Contribution] => 1000.00
[P_Name] => A
)
[1] => Array (
[Contribution] => 1001.00
[P_Name] => A
)
[2] => Array (
[Contribution] => 69.00
[P_Name] => B
)
)
Input:
$a=[['Contribution'=>1000,'P_Name'=>'A'],
['Contribution'=>1500,'P_Name'=>'B'],
['Contribution'=>2000,'P_Name'=>'C']];
$b=[['Contribution'=>100,'P_Name'=>'A'],
['Contribution'=>200,'P_Name'=>'B'],
['Contribution'=>300,'P_Name'=>'D']];
If you temporarily assign associative keys to the subarrays using array_column(), then you can leverage array_merge_recursive() to group on P_Name values, then call array_sum() to do the addition if there is more than one value to for a given P_Name.
Method #1: (Demo)
$keyed=array_merge_recursive(array_column($a,NULL,'P_Name'),array_column($b,NULL,'P_Name'));
foreach($keyed as $p_name=>$array){
$result[]=['Contribution'=>(is_array($array['Contribution'])?array_sum($array['Contribution']):$array['Contribution']),'P_Name'=>$p_name];
}
var_export($result);
Or just do a standard merge to create one array, then loop and add as you go. Finalize the output array with array_values() to reindex the elements.
Method #2: (Demo)
foreach(array_merge($a,$b) as $array){
if(isset($result[$array['P_Name']])){
$result[$array['P_Name']]['Contribution']+=$array['Contribution'];
}else{
$result[$array['P_Name']]=$array;
}
}
$result=array_values($result);
var_export($result);
Output: (from either method)
array (
0 =>
array (
'Contribution' => 1100,
'P_Name' => 'A',
),
1 =>
array (
'Contribution' => 1700,
'P_Name' => 'B',
),
2 =>
array (
'Contribution' => 2000,
'P_Name' => 'C',
),
3 =>
array (
'Contribution' => 300,
'P_Name' => 'D',
),
)
It is out of the scope of this question, but chances are the best approach would be to perform this grouping/addition via database query.
Here is a quick and dirty way to do it: Loop over both arrays, the outer loop fills the inner loop. If no match was fount, $x remails 0, and the value will be added to the inner loop. If a match is found, $x is 1 and the inner loop will break to continue the outer loop.
$a = [['a' => 10,'b' => 'g'], ['a' => 11,'b' => 'h']];
$b = [['a' => 1, 'b' => 'g'], ['a' => 2, 'b' => 'h'], ['a' => 3, 'b' => 'i']];
// now its fool proof.
function mergeData( $a, $b )
{
if( empty( $a ) && empty( $b ) )
return [];
if( empty( $a ) )
return $b;
if( empty( $b ) )
return $a;
foreach( $b AS $i => $c ) {
$x = 0;
foreach( $a AS $ii => $d ) {
if( $c['b'] == $d['b'] ) {
$a[ $ii ]['a'] += $c['a'];
$x = 1;
break;
}
}
if( !$x )
$a[] = $b[ $i ];
}
return $a;
}
Output
Array
(
[0] => Array
(
[a] => 11
[b] => g
)
[1] => Array
(
[a] => 13
[b] => h
)
[2] => Array
(
[a] => 3
[b] => i
)
)
Little bit different approach
$array1 = [
[
'Contribution' => 10,
'P_Name' => 'A'
],
[
'Contribution' => 1500,
'P_Name' => 'B'
]
];
$array2 = [
[
'Contribution' => 200,
'P_Name' => 'B'
],
[
'Contribution' => 100,
'P_Name' => 'C'
],
];
$array3 = array_map(function($elem) use (&$array2){
foreach($array2 as $i => &$a2){
if($a2['P_Name'] == $elem['P_Name']){
$a2['Contribution'] += $elem['Contribution'];
return;
}
}
return $elem;
},$array1);
$array3 = array_merge(array_filter($array3),$array2);
print_r($array3);
output:
Array
(
[0] => Array
(
[Contribution] => 10
[P_Name] => A
)
[1] => Array
(
[Contribution] => 1700
[P_Name] => B
)
[2] => Array
(
[Contribution] => 100
[P_Name] => C
)
)
You can use array_reduce(), array_map(), and array_sum():
<?php
function merge(array ...$sets)
{
/**
* group contributions by name
*/
$contributions = array_reduce(
$sets,
function (array $contributions, array $set) {
foreach ($set as $element) {
$name = $element['P_Name'];
$contribution = $element['Contribution'];
if (!array_key_exists($name, $contributions)) {
$contributions[$name] = [];
}
$contributions[$name][] = $contribution;
}
return $contributions;
},
[]
);
/**
* normalize the array so we remove the name as key, and return a tuple of name and contribution, with the desired
* structure
*/
return array_values(array_map(function (array $contribution, $name) {
return [
'Contribution' => array_sum($contribution),
'P_Name' => $name,
];
}, $contributions, array_keys($contributions)));
}
$a = [
[
'Contribution' => 1000,
'P_Name' => 'A',
],
[
'Contribution' => 1500,
'P_Name' => 'B',
],
];
$b = [
[
'Contribution' => 100,
'P_Name' => 'A',
],
[
'Contribution' => 200,
'P_Name' => 'B',
],
];
$merged = merge($a, $b);
var_dump($merged);
Note Because of using variadics, any number of arrays can be passed to merge(). Requires at least PHP 5.6, though.
For reference, see:
http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list
http://php.net/manual/en/function.array-reduce.php
http://php.net/manual/en/function.array-key-exists.php
http://php.net/manual/en/function.array-map.php
http://php.net/manual/en/function.array-sum.php
http://php.net/manual/en/function.array-values.php
http://php.net/manual/en/function.array-keys.php
For an example, see:
https://3v4l.org/EI4Tn
I'm looking for a way to order an array associative by a specific value, I'm not sure if it's possible. I tried it with array_multisort() and usort() functions, but I'm afraid that I can not get it.
Example:
$array[] = array('id' => 74215, 'type' => 'BOX');
$array[] = array('id' => 76123, 'type' => 'UNT');
$array[] = array('id' => 71231, 'type' => '');
$array[] = array('id' => 79765, 'type' => 'UNT');
$array[] = array('id' => 77421, 'type' => 'BOX');
If I want to order by 'BOX', then the array will be:
Array (
[0] => Array
(
[id] => 77421
[type] => 'BOX'
)
[1] => Array
(
[id] => 74215
[type] => 'BOX'
)
[2] => Array
(
[id] => 76123
[type] => 'UNT'
)
.
.
.
I could pass other string like 'UNT', and order by like that.
Is this possible??
I assume you want to "sort" by string match, first all those who match that string, after that all those that don't. Unless you have an archaic php version, this could work:
$sortvalue = 'BOX';
usort($array, function($a, $b) use ($sortvalue) {
if($a['type'] == $sortvalue) return -1;
elseif($b['type'] == $sortvalue) return 1;
else return 0;
});
this should put any 'BOX' entry to the front of your array.
If all others shall be grouped, instead of return 0 do return $a['type'] < $b['type'].
edit: integrated kamal pal's suggestion/correction
I'm not sure if PHP has it's own function that does that, but i write my own, hope it helps:
function sortArray($array_x, $key)
{
$added_indexes;
$new_array;
for($i=0;$i<count($array_x);$i++)
{
if($array_x[$i]['type']==$key){
$new_array[]=$array_x[$i];
$added_indexes[]=$i;
}
}
for($i=0;$i<count($array_x);$i++)
{
if(!in_array($i,$added_indexes))
{
$new_array[]=$array_x[$i];
}
}
return $new_array;
}
So when you do this:
$array[] = array('id' => 74215, 'type' => 'BOX');
$array[] = array('id' => 76123, 'type' => 'UNT');
$array[] = array('id' => 71231, 'type' => '');
$array[] = array('id' => 79765, 'type' => 'UNT');
$array[] = array('id' => 77421, 'type' => 'BOX');
print_r(sortArray($array,"BOX"));
Gives this:
Array
(
[0] => Array
(
[id] => 74215
[type] => BOX
)
[1] => Array
(
[id] => 77421
[type] => BOX
)
[2] => Array
(
[id] => 76123
[type] => UNT
)
[3] => Array
(
[id] => 71231
[type] =>
)
[4] => Array
(
[id] => 79765
[type] => UNT
)
)
Yeah I was thinking in a similar solution:
usort($array, function ($a, $b) {
return $a['type'] == 'BOX' ? -1 : ($b['type'] == 'BOX' ? 1 : 0);
});
I have an array looking like this:
Array(
['some_first_category'] => Array(
['some_first_name'] => Array(
[0]=>'first#email.com',
[1]=>'second#email.com',
[2]=>'third#email.com',
[3]=>'fourth#email.com' )
['some_second_name'] => Array (
[1]=>'first#email.com',
[2]=>'second#email.com')
['some_third_name'] => Array(
[1]=>'first#email.com',
[2]=>'second#email.com',
[3]=>'third#email.com',
[4]=>'fourth#email.com' )
['some_second_category'] => Array(
['some_first_name'] => Array(
[0]=>'first#email.com' )
['some_second_name'] => Array(
[1]=>'first#email.com',
[2]=>'second#email.com',
[3]=>'third#email.com',
[4]=>'fourth#email.com')
['some_third_name'] => Array(
[1]=>'first#email.com',
[2]=>'second#email.com'))
And I want to sort the array by the number of values of that has the names, In my case I want to become this array:
Array(
['some_first_category'] => Array(
['some_third_name'] => Array(
[1]=>'first#email.com',
[2]=>'second#email.com',
[3]=>'third#email.com',
[4]=>'fourth#email.com' )
['some_first_name'] => Array(
[0]=>'first#email.com',
[1]=>'second#email.com',
[2]=>'third#email.com',
[3]=>'fourth#email.com' )
['some_second_name'] => Array (
[1]=>'first#email.com',
[2]=>'second#email.com')
['some_second_category'] => Array(
['some_second_name'] => Array(
[1]=>'first#email.com',
[2]=>'second#email.com',
[3]=>'third#email.com',
[4]=>'fourth#email.com')
['some_third_name'] => Array(
[1]=>'first#email.com',
[2]=>'second#email.com')
['some_first_name'] => Array(
[0]=>'first#email.com' ))
This means sorting categories by name by the number(count) of values of the names. Someone can help me?
Thanks in advance,
Aäron
All you need is uasort
uasort($list, function ($a, $b) {
$a = count($a);
$b = count($b);
return ($a == $b) ? 0 : (($a < $b) ? -1 : 1);
});
Full Example
$list = Array(
'some_first_category' => Array(
'some_first_name' => Array(
0=>'first#email.com',
1=>'second#email.com',
2=>'third#email.com',
3=>'fourth#email.com' ),
'some_second_name' => Array (
1=>'first#email.com',
2=>'second#email.com'),
'some_third_name' => Array(
1=>'first#email.com',
2=>'second#email.com',
3=>'third#email.com',
4=>'fourth#email.com' )
),
'some_second_category' => Array(
'some_first_name' => Array(
0=>'first#email.com' ),
'some_second_name' => Array(
1=>'first#email.com',
2=>'second#email.com',
3=>'third#email.com',
4=>'fourth#email.com'),
'some_third_name' => Array(
1=>'first#email.com',
2=>'second#email.com'))
);
$list = array_map(function ($v) {
uasort($v, function ($a, $b) {
$a = count($a);
$b = count($b);
return ($a == $b) ? 0 : (($a < $b) ? 1 : - 1);
});
return $v;
}, $list);
print_r($list);
Output
Array
(
[some_first_category] => Array
(
[some_first_name] => Array
(
[0] => first#email.com
[1] => second#email.com
[2] => third#email.com
[3] => fourth#email.com
)
[some_third_name] => Array
(
[1] => first#email.com
[2] => second#email.com
[3] => third#email.com
[4] => fourth#email.com
)
[some_second_name] => Array
(
[1] => first#email.com
[2] => second#email.com
)
)
[some_second_category] => Array
(
[some_second_name] => Array
(
[1] => first#email.com
[2] => second#email.com
[3] => third#email.com
[4] => fourth#email.com
)
[some_third_name] => Array
(
[1] => first#email.com
[2] => second#email.com
)
[some_first_name] => Array
(
[0] => first#email.com
)
)
)
Using uksort:
uksort($yourArray, function($a, $b) { return count($b) - count($a); });
Using array_multisort:
array_multisort(array_map('count', $yourArray), SORT_DESC, $yourArray);
and you can see uasort as well
best of luck :)
You should use usort function. Refer here.
function sort_sub($a,$b)
{
$res= count($b)-count($a);
return $res;
}
usort($array_name,'sort_sub')
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Sort multidimensional array by multiple keys
I am trying to find some way how to sort array by key name, but nothing worked so far. The tricky part for me is to sort array by grouping 3 keys. I have this array.
[0] => Array
(
[id] => 8
[zbo_data] => blah
)
[1] => Array
(
[id] => 6
[szn_data] => blah
)
[2] => Array
(
[id] => 5
[gcz_data] => blah
)
[3] => Array
(
[id] => 3
[gcz_data] => blah
)
[4] => Array
(
[id] => 2
[zbo_data] => blah
)
[5] => Array
(
[id] => 1
[szn_data] => blah
)
And I need to sort it by group of 3 in this order: szn_data, zbo_data, gcz_data but I also need to keep the order of [id] (basically primary order by szn_data, zbo_data, gcz_data, secondary [id]). Is there a solution? Or should I construct array differently to be able to sort it? I am trying to figure this out for over 6 hours. Any help is much appreciated.
My desired output is:
[0] => Array
(
[id] => 6
[szn_data] => blah
)
[1] => Array
(
[id] => 8
[zbo_data] => blah
)
[2] => Array
(
[id] => 5
[gcz_data] => blah
)
[3] => Array
(
[id] => 1
[szn_data] => blah
)
[4] => Array
(
[id] => 2
[zbo_data] => blah
)
[5] => Array
(
[id] => 3
[gcz_data] => blah
)
Use usort and implement your comparison function as you wish. For example:
$result = usort($arr, function($a,$b) {
$keys = array('szn_data', 'zbo_data', 'gcz_data');
foreach ($keys as $key) {
// make sure to add here handling of missing keys
$diff = strcmp($b[$key], $a[$key]);
if ($diff!=0) {
return $diff;
}
}
return $b['id'] - $a['id'];
});
Or like this, for any order from max to the min listed in one array
$arr = array (
array(
'id' => 8,
'zbo_data' => 'blah'
),
array(
'id' => 6,
'szn_data' => 'blah'
),
array(
'id' => 5,
'gcz_data' => 'blah'
),
array(
'id' => 3,
'gcz_data' => 'blah'
),
array(
'id' => 2,
'zbo_data' => 'blah'
),
array(
'id' => 1,
'szn_data' => 'blah'
)
);
usort($arr, "my_func");
var_dump($arr);
function my_func($a, $b)
{
$vars = array('szn_data', 'zbo_data', 'gcz_data'); // order of the keys
$id1 = $a['id']; $id2 = $b['id']; unset($a['id'], $b['id']);
$index1 = array_search(key($a), $vars);
$index2 = array_search(key($b), $vars);
if ($index1 == $index2) {
if ($id1 == $id2) return 0;
return ($id1 < $id2) ? 1 : -1;
}
return ($index1 < $index2) ? -1 : 1;
}
ps:
basically primary order by szn_data, zbo_data, gcz_data, secondary
[id]
It does not correspond to your desired output. Secondary means comparison of id when other keys are the same.
ps: Updated - this code is NOT nice or perfect, but it will give you what you need
$vars = array('szn_data', 'zbo_data', 'gcz_data');
$arr = array (
array(
'id' => 8,
'zbo_data' => 'blah'
),
array(
'id' => 6,
'szn_data' => 'blah'
),
array(
'id' => 5,
'gcz_data' => 'blah'
),
array(
'id' => 3,
'gcz_data' => 'blah'
),
array(
'id' => 2,
'zbo_data' => 'blah'
),
array(
'id' => 1,
'szn_data' => 'blah'
)
);
$temp = array();
$cnt = count($arr);
foreach($arr as $item)
{
foreach($vars as $v)
{
if (isset($item[$v])) { $temp[$v][$item['id']] = $item; break; }
}
}
// sort by id
foreach($vars as $v)
{
krsort($temp[$v]);
$temp[$v] = array_values($temp[$v]);
}
$arr = array(); $i = 0; $j = 0;
$completed = false;
do {
foreach($vars as $v)
{
if ($i++>=$cnt) { $completed = true; break; }
if (isset($temp[$v][$j])) $arr[] = $temp[$v][$j];
}
$j++;
} while (!$completed);
// output
var_dump($arr)