Sort multi-dimensional array by considering 2 different properties - php

I have an array for example
Array
(
[0] => Array
(
[id] => 6
[name] => ah
[order] => 4
)
[1] => Array
(
[id] => 5
[name] => hz
[order] =>
)
[2] => Array
(
[id] => 7
[name] => ch
[order] =>
)
[3] => Array
(
[id] => 5
[name] =>
[order] =>
)
[4] => Array
(
[id] => 4
[name] => zh
[order] => 1
)
)
It needs to be sorted first by "order", if order isn't available, it is sorted in alphabetical order with the "name" (but those arrays goes after all the arrays that have the sort order), and if no "order" and no "name", it goes at the end of the array.
So the above array would need to become:
Array
(
[0] => Array
(
[id] => 4
[name] => zh
[order] => 1
)
[1] => Array
(
[id] => 6
[name] => ah
[order] => 4
)
[2] => Array
(
[id] => 7
[name] => ch
[order] =>
)
[3] => Array
(
[id] => 5
[name] => hz
[order] =>
)
[4] => Array
(
[id] => 5
[name] =>
[order] =>
)
)
I've tried some for looping but nothing close to a solution.

Have you looked at array_multisort?
foreach ($data as $key => $row) {
$name[$key] = $row['name'];
$order[$key] = $row['order'];
}
array_multisort($name, SORT_DESC, $order, SORT_ASC, $data);
PHP array multisort

array_multisort() might not provide enough control to achieve the sorting you require.
As an alternative, you could use uasort() and provide a custom comparison function.
For example:
function compare($a, $b) {
if (empty($a['order']) && !empty($b['order'])) {
return 1;
}
if (!empty($a['order']) && empty($b['order'])) {
return -1;
}
if ($a['order'] == $b['order']) {
return strnatcmp($a['name'], $b['name']);
}
return ($a['order'] < $b['order']) ? -1 : 1;
}
uasort($arr, 'compare');

Related

Flatten Array php

I'm trying to flat a multidimensional array to a given specific format.
I have a tree that is saved as a nested array, which is ok, but the function given to render the array in the UI expects only one array and, per each child, an independent array. Instead of the nested array, each option should be at the same level.
This is how my var_dump of my array:
(
[id] => 1
[name] => some data.
[emoji] => 🐕
[parent_id] =>
[children] => Array
(
[0] => Array
(
[id] => 2
[name] => Food
[emoji] => 🥩
[parent_id] => 1
[children] => Array
(
)
)
[1] => Array
(
[id] => 3
[name] => some other data
[emoji] => 😌
[parent_id] => 1
[children] => Array
(
[0] => Array
(
[id] => 4
[name] => Massages
[emoji] => 💆
[parent_id] => 3
[children] => Array
(
)
)
[1] => Array
(
[id] => 5
[name] => Games
[emoji] => 🎾
[parent_id] => 3
[children] => Array
(
)
)
)
)
)
)
)
And the expected result should be:
0] => Array
(
[id] => 1
[name] => Rusty Corp.
[emoji] => 🐕
[parent_id] =>
)
[1] => Array
(
[id] => 2
[name] => Food
[emoji] => 🥩
[parent_id] => 1
)
[2] => Array
(
[id] => 3
[name] => Canine Therapy
[emoji] => 😌
[parent_id] => 1
)
[3] => Array
(
[id] => 4
[name] => Massages
[emoji] => 💆
[parent_id] => 3
)
[4] => Array
(
[id] => 5
[name] => Games
[emoji] => 🎾
[parent_id] => 3
)
I tried different approaches like array_merge or custom flattening function but can't nail with the expected results, any suggestions?
Edit:
This is my flatten function:
private function flatten_array( array $array ) {
$return = array();
array_walk_recursive(
$array,
function( $a ) use ( &$return ) {
$return[] = $a;
}
);
return $return;
}
Here is a recursive function that will flatten the array, it will not take into account the null value of parent_id on the root element. Also the flattened array will start with the most nested elements at the start of the array and root element at the end.
function flatten_array($array, $flattened = []) {
$current = [];
foreach ($array as $key => $value) {
if (is_array($value))
$flattened = array_merge($flattened, flatten_array($value));
else
$current[$key] = $value;
}
$flattened[] = $current;
return array_filter($flattened);
}

sort an array with another array which has sorted keys

How to sort an 1st array with 2nd array which has sorted keys in 2nd array without using any loop.
1st Array.
$chunk = array(
[0] => Array
(
[id] => 212
[order] => 1
[title] => fdfdfdfdf
)
[1] => Array
(
[id] => 5
[order] => 2
[title] =>
)
[2] => Array
(
[id] => 781
[order] => 3
[title] =>
)
)
2nd array with sorted keys of 1st array.
$sort = array
(
[2] => 2
[0] => 0
[1] => 1
)
You could use array_map for that:
$arr = array_map(function($val) use($chunk){
return $chunk[$val];
}, $sort);
This is the output:
Array
(
[2] => Array
(
[id] => 781
[order] => 3
[title] =>
)
[0] => Array
(
[id] => 212
[order] => 1
[title] => fdfdfdfdf
)
[1] => Array
(
[id] => 5
[order] => 2
[title] =>
)
)
Now, if you want the keys to be 0,1,2..., you can use array_values, after mapping:
$arr = array_values($arr);
And the output:
Array
(
[0] => Array
(
[id] => 781
[order] => 3
[title] =>
)
[1] => Array
(
[id] => 212
[order] => 1
[title] => fdfdfdfdf
)
[2] => Array
(
[id] => 5
[order] => 2
[title] =>
)
)
Of course, there is no function for this. You'll have to do something similar
<?php
$chunk = [
// data
];
$sorted = [];
$sort = [
// ordered keys
];
foreach($sort as $keyToFind) {
foreach($chunk as $arrayElement) {
if($arrayElement['id'] == $keyToFind)) {
$sorted[$keyToFind] = $arrayElement;
}
}
}
As you can see, this is a bit time and ressources consumming because of the two imbricated foreaches. Let's hope your arrays are not so big

Sorting multidimentional Array Keys As Number

I'm having a problem to sort multidimensional array.
print_r($myarray); is giving following output:
Array
(
[0] => Array
(
[ID] => 10
[Code] => 12-111
[Name] => putup1
)
[1] => Array
(
[ID] => 11
[Code] => 12-21
[Name] => putup2
)
[2] => Array
(
[ID] => 12
[Code] => 12-1
[Name] => putup2
)
)
I took a reference from this link: Sort MultiDimensional Array and sorted using column Code. it given me output like this:
Array
(
[0] => Array
(
[ID] => 10
[Code] => 12-1
[Name] => putup1
)
[1] => Array
(
[ID] => 12
[Code] => 12-111
[Name] => putup2
)
[2] => Array
(
[ID] => 11
[Code] => 12-21
[Name] => putup2
)
)
And I expecting output like :
Array
(
[0] => Array
(
[ID] => 10
[Code] => 12-1
[Name] => putup1
)
[2] => Array
(
[ID] => 11
[Code] => 12-21
[Name] => putup2
)
[1] => Array
(
[ID] => 12
[Code] => 12-111
[Name] => putup2
)
)
Is it possible? Please suggest me...
Thank you :)
You are currently sorting on code, but as text and not as a number. To sort it as you want, you have to write a comparison function that indicates whether one code is bigger than another:
function sortByCode($a, $b) {
$aParts = explode('-', $a['Code']);
$bParts = explode('-', $b['Code']);
for ($i = 0; $i < count($aParts); $i++) {
if ($aParts[$i] < $bParts[$i]) {
return -1;
} else if ($aParts[$i] > $bParts[$i]) {
return 1;
}
}
return 0;
}
usort($myArray, 'sortByCode');

How to merge two 2D php arrays while I want to add up some values?

I have two php arrays like these:
Array
(
[0] => Array
(
[id] => 712
[count] => 5
)
[1] => Array
(
[id] => 5510
[count] => 3
)
)
Array
(
[0] => Array
(
[id] => 856
[count] => 7
)
[1] => Array
(
[id] => 5510
[count] => 10
)
)
Now I want to make the merge result like this:
Array
(
[0] => Array
(
[id] => 712
[count] => 5
)
[1] => Array
(
[id] => 856
[count] => 3
)
[2] => Array
(
[id] => 5510
[count] => 13
)
)
Just add the count up of those having the same id.
And of course the real array is much more complicated than the example above.
Can you show me a way to deal with this?
This should work for you
/**
* merge counts for arrays
* #param array $arrays,...
* #return array
*/
function merge_counts(){
$arrays = func_get_args();
$ret = array();
foreach($arrays as $arr){
foreach($arr as $item){
if(array_key_exists($k = $item['id'], $ret)){
$ret[$k]['count'] += $item['count'];
}
else {
$ret[$k] = $item;
}
}
}
return array_values($ret);
}
Usage
$result = merge_counts($one, $two);
print_r($result);
// alternatively...
// $result = merge_counts($one, $two, $three, ...);
Output
Array
(
[0] => Array
(
[id] => 712
[count] => 5
)
[1] => Array
(
[id] => 5510
[count] => 13
)
[2] => Array
(
[id] => 856
[count] => 7
)
)

array difference

I have this array lets call it array 1
Array
(
[0] => Array
(
[Machine] => Array
(
[id] => 7
[name] => XYZ
[priority] => 1
)
[Software] => Array
(
[id] => 472
)
)
[1] => Array
(
[Machine] => Array
(
[id] => 6
[name] => ABC
[priority] => 0
)
[Software] => Array
(
[id] => 470
)
)
[2] => Array
(
[Machine] => Array
(
[id] => 1
[name] => IEU
[priority] => 3
)
[Software] => Array
(
[id] => 471
)
)
)
Then I have another array lets call it array 2
Array
(
[0] => 7
[1] => 5
[2] => 4
[3] => 3
[4] => 6
)
If array 2 doesnt have [Machine][id] then I want it to be removed from array 1. Like in above example 1 will removed
[2] => Array
(
[Machine] => Array
(
[id] => 1
[name] => IEU
[priority] => 3
)
[Software] => Array
(
[id] => 471
)
)
any idea on how to achieve that. Thanks
Perhaps..
foreach ($array1 AS $key => $array) {
if (!in_array($array['Machine']['id'], $array2))
unset($array1[$key]);
}
try something like :
$new_array = array();
foreach ($array1 as $platform)
{
if (in_array($platform["Machine"]["id"], $array2))
{
$new_array[] = $platform;
}
}
return $new_array;

Categories