Make unique array and add the amount in php - php

I have to make the array to unique array list if the invoice_products_id is same and for the same invoice_products_id i have add the amount. I am able to make it unique but amount is not adding.
0 =>{
'id' => 9,
'invoice_products_id' => 2,
'amount' => 1.8,
},
1 =>{
'id' => 10,
'invoice_products_id' => 3,
'amount' => 2,
},
2 =>{
'id' => 11,
'invoice_products_id' => 2,
'amount' => 1.1,
},
3 =>{
'id' => 12,
'invoice_products_id' => 3,
'amount' => 1.2,
},
code:
$invtax=[];
foreach($invoiceProduct['invoice_taxes'] as $taxkey=>$taxval){
$ref=$taxval->invoice_products_id;
if(isset($invtax[$ref])){
$invtax[$ref]->amount+=$taxval->amount;
}else{
$invtax[$ref]=$taxval;
}
}
result:
2 =>{
'id' => 11,
'invoice_products_id' => 2,
'amount' => 2.9,
},
3 =>{
'id' => 12,
'invoice_products_id' => 3,
'amount' => 1.2,
},
expected:
2 =>{
'id' => 11,
'invoice_products_id' => 2,
'amount' => 2.9,
},
3 =>{
'id' => 12,
'invoice_products_id' => 3,
'amount' => 3.2,
},

Making use of array_filter and array_walk functions
See here for live example: https://3v4l.org/rXXR9
Input
<?php
$arr = [
[
'id' => 9,
'invoice_products_id' => 2,
'amount' => 1.8,
],[
'id' => 10,
'invoice_products_id' => 3,
'amount' => 2,
],[
'id' => 11,
'invoice_products_id' => 2,
'amount' => 1.1,
],[
'id' => 12,
'invoice_products_id' => 3,
'amount' => 1.2,
],
];
Program
<?php
$assorted_heap = [];
$filter_function = function($v, $k) {
global $assorted_heap;
if (isset($assorted_heap[$v['invoice_products_id']])) {
$assorted_heap[$v['invoice_products_id']][1] += $v['amount'];
return false;
} else {
$assorted_heap[$v['invoice_products_id']] = [$k, $v['amount']];
}
return true;
};
$walk_function = function(&$v, $k) {
global $assorted_heap;
$v['amount'] = $assorted_heap[$v['invoice_products_id']][1];
};
$new_arr = array_filter($arr,
$filter_function,
ARRAY_FILTER_USE_BOTH
);
array_walk($new_arr, $walk_function);
unset($assorted_heap);
print_r($new_arr);
Output
Array
(
[0] => Array
(
[id] => 9
[invoice_products_id] => 2
[amount] => 2.9
)
[1] => Array
(
[id] => 10
[invoice_products_id] => 3
[amount] => 3.2
)
)

Related

How to merge arrays based on value in php?

I am having 2 arrays and i have to merge that arrays with similar values. i tried for each and basic functions of php for array merging but not getting proper result.
i tried below thing but it wont work for me as i am having multiple data in second array. as you can see in child array i am having multiple records and i want to keep that together inside base array.
$base= [
['id' => 1],
['id' => 2],
['id' => 3],
['id' => 4],
];
$child = [
['id' => 1, 'size' => 'SM'],
['id' => 1, 'size' => 'LK'],
['id' => 2, 'size' => 'XL'],
['id' => 4, 'size' => 'LG'],
['id' => 3, 'size' => 'MD'],
];
foreach(array_merge($base, $child) as $el){
$merged[$el['id']] = ($merged[$el['id']] ?? []) + $el;
}
Output :
array (
1 =>
array (
'id' => 1,
'size' => 'SM',
),
2 =>
array (
'id' => 2,
'size' => 'XL',
),
3 =>
array (
'id' => 3,
'size' => 'MD',
),
4 =>
array (
'id' => 4,
'size' => 'LG',
),
)
desired output :
array (
1 =>
array (
'id' => 1,
1 => array('size' => 'SM'),
2 => array('size' => 'LK'),
),
2 =>
array (
'id' => 2,
1 => array('size' => 'XL'),
),
3 =>
array (
'id' => 3,
1 => array('size' => 'MD'),
),
4 =>
array (
'id' => 4,
1 => array('size' => 'LG'),
),
)
Because your array $child have same key id value, and every you save the array, it always destroyed old array with same key id.
Here the working code :
<?php
$base= [
['id' => 1],
['id' => 2],
['id' => 3],
['id' => 4],
];
$child = [
['id' => 1, 'size' => 'SM'],
['id' => 1, 'size' => 'LK'],
['id' => 2, 'size' => 'XL'],
['id' => 4, 'size' => 'LG'],
['id' => 3, 'size' => 'MD'],
];
foreach(array_merge($base, $child) as $el){
if(!isset($el['size'])){ // $base doesn't have 'size' key
$merged[$el['id']] = []; // fill with empty array
}else{
$merged[$el['id']][] = $el;
}
// bellow code is for start array index from 1 instead of 0
array_unshift($merged[$el['id']],"");
unset($merged[$el['id']][0]);
}
print_r($merged);

Counting expenses for categories stored in tree like array

I have an app where users can store their expenses and assign it to categories. Categories have tree structure, without depth limit and users can assign expense to any category (children, parent or middle). What I want to do is to count sum of expenses for all categories in tree structure. Lets simplify things and assume I have array with categories:
$categories = [
0 => [
'id' => 1,
'name' => 'Car',
'expenses_sum' => 0,
'subcategories' => [
0 => [
'id' => 2,
'name' => 'Gas',
'expenses_sum' => 0,
'subcategories' => [
0 => [
'id' => 3,
'name' => 'Orlen',
'expenses_sum' => 300,
'subcategories' => [
0 => [
'id' => 4,
'name' => 'Orlen A',
'expenses_sum' => 100,
'subcategories' => []
],
1 => [
'id' => 5,
'name' => 'Orlen B',
'expenses_sum' => 100,
'subcategories' => []
],
],
],
],
],
],
],
];
What I want do do is to go to the deepest level ("Orlen A" and "Orlen B"), sum expenses from that level, add it to the parent level ("Orlen") and store as the new "expenses_sum", so it should be: 100 + 100 + 300 = 500 and repeat it to the top level.
My code to do that looks like this:
function sumCategory(&$category) {
if (isset($category['subcategories'])) {
foreach ($category['subcategories'] as $subCategory) {
$subCategory['expenses_sum'] = sumCategory($subCategory);
$category['expenses_sum'] += $subCategory['expenses_sum'];
}
}
return $category['expenses_sum'];
}
foreach ($categories as $index => $category) {
$categories[$index]['expenses_sum'] = sumCategory($category);
}
echo '<pre>';
print_r($categories);
echo '</pre>';
Code counts properly sum at all levels, but the problem is that finally I got $categories array with modfied only "expenses_sum" at the top level and categories in the middle stays not modified. I tried to pass $categories to function by refference, but it doesnt help. Any tips what should I correct?
I have simplified problem, so you can easily grab all above code to test things on your own.
To clarify things: at the end I expect my array will be as follow:
$categories = [
0 => [
'id' => 1,
'name' => 'Car',
'expenses_sum' => 500, //500 + 0
'subcategories' => [
0 => [
'id' => 2,
'name' => 'Gas',
'expenses_sum' => 500, //500 + 0
'subcategories' => [
0 => [
'id' => 3,
'name' => 'Orlen',
'expenses_sum' => 500, //100 + 100 + 300
'subcategories' => [
0 => [
'id' => 4,
'name' => 'Orlen A',
'expenses_sum' => 100,
'subcategories' => []
],
1 => [
'id' => 5,
'name' => 'Orlen B',
'expenses_sum' => 100,
'subcategories' => []
],
],
],
],
],
],
],
];
$categories = [
0 => [
'id' => 1,
'name' => 'Car',
'expenses_sum' => 0,
'subcategories' => [
0 => [
'id' => 2,
'name' => 'Gas',
'expenses_sum' => 0,
'subcategories' => [
0 => [
'id' => 3,
'name' => 'Orlen',
'expenses_sum' => 300,
'subcategories' => [
0 => [
'id' => 4,
'name' => 'Orlen A',
'expenses_sum' => 100,
'subcategories' => []
],
1 => [
'id' => 5,
'name' => 'Orlen B',
'expenses_sum' => 100,
'subcategories' => []
],
],
],
],
],
],
],
];
function expensesSum($category) {
$sum = $category['expenses_sum'] ;
foreach($category['subcategories'] as $subCategory) {
$sum += expensesSum($subCategory);
}
return $sum;
}
function calculateExpenses(&$categories) {
foreach($categories as $index => $category) {
// do subs first
calculateExpenses($categories[$index]['subcategories']);
// then parent
$categories[$index]['expenses_sum'] = expensesSum($category);
}
return $categories;
}
print_r(calculateExpenses($categories));
Output:
Array
(
[0] => Array
(
[id] => 1
[name] => Car
[expenses_sum] => 500
[subcategories] => Array
(
[0] => Array
(
[id] => 2
[name] => Gas
[expenses_sum] => 500
[subcategories] => Array
(
[0] => Array
(
[id] => 3
[name] => Orlen
[expenses_sum] => 500
[subcategories] => Array
(
[0] => Array
(
[id] => 4
[name] => Orlen A
[expenses_sum] => 100
[subcategories] => Array
(
)
)
[1] => Array
(
[id] => 5
[name] => Orlen B
[expenses_sum] => 100
[subcategories] => Array
(
)
)
)
)
)
)
)
)
)
function calculateExpenses($categories) {
$expenses = 0;
foreach($categories as $category) {
$expenses += $category['expenses_sum'];
$expenses += calculateExpenses($category['subcategories']);
}
return $expenses;
}
echo calculateExpenses($categories);

Array_slice in multidimensional array? But a different output

I have an array in php like this :
$multid_array = array(
"url" => "www.checkmyhouse.cpm",
"date" => "2019/12/12",
"minor" => 1,
"sittingroom" => 1,
"dinningroom" => 2,
"toilet" => 2,
"parking" => 1,
"bedroom" => 2,
"garage" => 2,
"rooms" => 4,
"garden" => 1,
"url_1" => "-sameurl-",
"date_1" => "2019/12/3",
"minor_1" => 3,
"sittingroom_1" => 2,
"dinningroom_1" => 2,
"toilet_1" => 3,
"parking_1" => 1,
"bedroom_1" => 2,
"garage_1" => 6,
"rooms_1" => 6,
"garden_1" => 1,
"url_2" => "-sameurl-",
"date_2" => "2019/12/5",
"minor_2" => 3,
"sittingroom_2" => 2,
"dinningroom_2" => 2,
"toilet_2" => 3,
"parking_2" => 1,
"bedroom_2" => 5,
"garage_2" => 6,
"rooms_2" => 9,
"garden_2" => 1,
);
I have searched around, found this link. but not been able to figure it out. keep getting close.
array_slice in multidimensional array?
This is the output I would like:
$array =
[
"levels" => array(
"0" => array(
"url" => "www.checkmyhouse.cpm",
"date" => "2019/12/1",
"minor" => 1,
"sittingroom" => 1,
"dinningroom" => 2,
"toilet" => 2,
"parking" => 1,
"bedroom" => 2,
"garage" => 2,
"rooms" => 5,
"garden" => 1,
),
"1" => array(
"url" => "-sameurl-",
"date" => "2019/12/3",
"minor" => 3,
"sittingroom" => 2,
"dinningroom" => 2,
"toilet" => 3,
"parking" => 1,
"bedroom" => 2,
"garage" => 6,
"rooms" => 6,
"garden" => 1,
),
"2" => array(
"url" => "-sameurl-",
"date" => "2019/12/5",
"minor" => 3,
"sittingroom" => 2,
"dinningroom" => 2,
"toilet" => 3,
"parking" => 1,
"bedroom" => 5,
"garage" => 6,
"rooms" => 9,
"garden" => 1,
)
)
];
Just trying to rearrange it. but I have used array_slice and could only get the output of the first 9 elements.
array_splice($multid_array,9);
But I want to run it automatically, so in case more information gets added into the array then it would still work
Why not use simple for loop: (in this case you can have various number of field in each array and they don't need to be fixed as when use array_chunk)
$multid_array = array("url" => "www.checkmyhouse.cpm","date" => "2019/12/12","url_1" => "-sameurl-","date_1" => "2019/12/3","url_2" => "-sameurl-","date_2" => "2019/12/5",);
$ans = [];
foreach($multid_array as $k => $v) {
$parts = explode("_", $k);
$pk = 0; //default as 0 as when no prefix set to key "0"
if (count($parts) > 1) { // check if has suffix
$pk = $parts[1];
$k = $parts[0];
}
if (!isset($ans[$pk]))
$ans[$pk] = []; // init array if first time
$ans[$pk][$k] = $v;
}
Now $ans will contain your data - you can add "levels" key if you wish.
This will only works if you have "_" saved to mark inner indexes and they are not used in the actual keys

Sort Multi-dimensional Array in PHP with multiple conditionals

I'm trying to build up a result array from a DB query and basicly I was wondering if the following would be possible
Array content:
Array
(
[0] => Array
(
[Section_Id] => 1
[Section_Name] => "Section1"
[Section_Parent] => NULL
[Section_Position] => 0
[Section_Depth] => 0
)
[1] => Array
(
[Section_Id] => 3
[Section_Name] => "Section2"
[Section_Parent] => NULL
[Section_Position] => 1
[Section_Depth] => 0
)
[2] => Array
(
[Section_Id] => 4
[Section_Name] => "SubSection1ForSection2"
[Section_Parent] => 3
[Section_Position] => 0
[Section_Depth] => 1
)
[3] => Array
(
[Section_Id] => 2
[Section_Name] => "SubSection1ForSection1"
[Section_Parent] => 1
[Section_Position] => 0
[Section_Depth] => 1
)
)
If you would Sort this one lets say on Section_Position it would return something like:
usort($sections, function($a, $b) {
return $a['section_position'] - $b['section_position'];
});
Section1
SubSection1ForSection2
SubSection1ForSection1
Section2
Whilst I need it to order the Sections with their respective childs:
Section1
SubSection1ForSection1
Section2
SubSection1ForSection2
I assume Somehow Duplicate Question is the way to think but I can't seem to find a way to make this work for me.
Is there a way to do this or do I have to make a workaround with forloop-gets so that I first get all the values for depth one and then using the name of the section to get all the values of depth two and so forth?
(Sorry for my english.)
Okay this might be an ugly solution but if you put everything in a function it look good :). The good thing is that it will work in your scenario.
Code:
$inputData = array(
array(
'Section_Id' => 1,
'Section_Name' => "Section1",
'Section_Parent' => NULL,
'Section_Position' => 1,
'Section_Depth' => 0,
),
array(
'Section_Id' => 2,
'Section_Name' => "Section2",
'Section_Parent' => NULL,
'Section_Position' => 0,
'Section_Depth' => 0
),
array(
'Section_Id' => 4,
'Section_Name' => "SubSection2ForSection2",
'Section_Parent' => 2,
'Section_Position' => 1,
'Section_Depth' => 1
),
array(
'Section_Id' => 5,
'Section_Name' => "SubSection1ForSection2",
'Section_Parent' => 2,
'Section_Position' => 0,
'Section_Depth' => 1
),
array(
'Section_Id' => 3,
'Section_Name' => "SubSection1ForSection1",
'Section_Parent' => 1,
'Section_Position' => 0,
'Section_Depth' => 1
)
);
$parentRecords = array();
$childRecords = array();
$sorted = array();
/* split in two collections */
foreach ($inputData as $sectionData) {
if (is_null($sectionData['Section_Parent'])) {
/* assume this is a parent */
$parentRecords[] = $sectionData;
} else {
/* assume we are on child row */
$childRecords[] = $sectionData;
}
}
/* now first order parents by Section_Position */
usort($parentRecords, function($a, $b) {
if ($a['Section_Position'] == $b['Section_Position']) {
return 0;
}
return $a['Section_Position'] > $b['Section_Position'] ? 1 : -1;
});
/* now the actual sorting */
foreach ($parentRecords as $parentData) {
$parentId = $parentData['Section_Id'];
/* now get all children of this parent */
$parentChildren = array();
foreach ($childRecords as $childData) {
if ($childData['Section_Parent'] == $parentId) {
$parentChildren[] = $childData;
}
}
/* now sort the children by Section_Position */
usort($parentChildren, function($a, $b) {
if ($a['Section_Position'] == $b['Section_Position']) {
return 0;
}
return $a['Section_Position'] > $b['Section_Position'] ? 1 : -1;
});
$sorted[] = $parentData;
$sorted = array_merge($sorted, $parentChildren);
}
echo '<pre>' . print_r($sorted, true) . '</pre>';
exit;
OUTPUT:
Array
(
[0] => Array
(
[Section_Id] => 2
[Section_Name] => Section2
[Section_Parent] =>
[Section_Position] => 0
[Section_Depth] => 0
)
[1] => Array
(
[Section_Id] => 5
[Section_Name] => SubSection1ForSection2
[Section_Parent] => 2
[Section_Position] => 0
[Section_Depth] => 1
)
[2] => Array
(
[Section_Id] => 4
[Section_Name] => SubSection2ForSection2
[Section_Parent] => 2
[Section_Position] => 1
[Section_Depth] => 1
)
[3] => Array
(
[Section_Id] => 1
[Section_Name] => Section1
[Section_Parent] =>
[Section_Position] => 1
[Section_Depth] => 0
)
[4] => Array
(
[Section_Id] => 3
[Section_Name] => SubSection1ForSection1
[Section_Parent] => 1
[Section_Position] => 0
[Section_Depth] => 1
)
)
NOTE: first sort is done by respect to parents Section_Position and then to child's Section_Position
U P D A T E
First I want to say sorry to moderators for the long long discussion that we had with #Akorna but I needed to give him this code and I think it will do the job for the future. So #Akorna the code that should work for you is this one:
$inputData = array(
array(
'section_id' => 333,
'section_depth' => 1,
'section_parent' => 332,
'section_position' => 0,
'section_title' => 'Introduction'),
array(
'section_id' => 334,
'section_depth' => 1,
'section_parent' => 332,
'section_position' => 1,
'section_title' => 'Glossary'),
array(
'section_id' => 335,
'section_depth' => 1,
'section_parent' => 332,
'section_position' => 2,
'section_title' => 'Commands'),
array(
'section_id' => 336,
'section_depth' => 1,
'section_parent' => 332,
'section_position' => 3,
'section_title' => 'Components'),
array(
'section_id' => 337,
'section_depth' => 2,
'section_parent' => 336,
'section_position' => 0,
'section_title' => 'Introduction'),
array(
'section_id' => 407,
'section_depth' => 2,
'section_parent' => 401,
'section_position' => 2,
'section_title' => 'Web Application'),
array(
'section_id' => 338,
'section_depth' => 2,
'section_parent' => 336,
'section_position' => 1,
'section_title' => 'AbstractContainer'),
array(
'section_id' => 406,
'section_depth' => 2,
'section_parent' => 401,
'section_position' => 1,
'section_title' => 'Web Application'),
array(
'section_id' => 339,
'section_depth' => 2,
'section_parent' => 336,
'section_position' => 2,
'section_title' => 'ActionsContainer'),
array(
'section_id' => 340,
'section_depth' => 2,
'section_parent' => 336,
'section_position' => 3,
'section_title' => 'BrowserIncompatibility'),
array(
'section_id' => 404,
'section_depth' => 2,
'section_parent' => 402,
'section_position' => 3,
'section_title' => 'Web Application'),
array(
'section_id' => 341,
'section_depth' => 2,
'section_parent' => 336,
'section_position' => 4,
'section_title' => 'CollapsibleContainer'),
array(
'section_id' => 342,
'section_depth' => 2,
'section_parent' => 336,
'section_position' => 5,
'section_title' => 'DetailsContainer'),
array(
'section_id' => 343,
'section_depth' => 2,
'section_parent' => 336,
'section_position' => 6,
'section_title' => 'DynamicMenu'),
array(
'section_id' => 403,
'section_depth' => 2,
'section_parent' => 402,
'section_position' => 1,
'section_title' => 'Web Application'),
array(
'section_id' => 344,
'section_depth' => 2,
'section_parent' => 336,
'section_position' => 7,
'section_title' => 'Settings'),
array(
'section_id' => 345,
'section_depth' => 2,
'section_parent' => 336,
'section_position' => 8,
'section_title' => 'SubfilesViewer'),
array(
'section_id' => 346,
'section_depth' => 2,
'section_parent' => 336,
'section_position' => 9,
'section_title' => 'Taxonomy Management'),
array(
'section_id' => 402,
'section_depth' => 1,
'section_parent' => 400,
'section_position' => 2,
'section_title' => 'Web Application'),
array(
'section_id' => 401,
'section_depth' => 1,
'section_parent' => 400,
'section_position' => 1,
'section_title' => 'Web Application'),
array(
'section_id' => 347,
'section_depth' => 2,
'section_parent' => 336,
'section_position' => 10,
'section_title' => 'UploadQueue'),
array(
'section_id' => 400,
'section_depth' => 0,
'section_parent' => null,
'section_position' => 5,
'section_title' => 'Web Application'),
array(
'section_id' => 332,
'section_depth' => 0,
'section_parent' => null,
'section_position' => 3,
'section_title' => 'Web Application')
);
/* first order by section_depth and then by section_position */
$inputData = array_orderby($inputData, 'section_depth', SORT_ASC, 'section_position', SORT_ASC);
$parents = array();
$sortedByParent = false;
while (!$sortedByParent) {
$elems = array_splice($inputData, count($inputData) - 1, 1);
if (!count($elems)) {
$sortedByParent = true;
$inputData = array_merge($inputData, $parents);
continue;
}
$elem = $elems[0];
if ($elem['section_depth'] == 0) {
if (!isset($elem['children'])) {
$elem['children'] = array();
}
$parents[] = $elem;
} else {
$inputData = put_in_parent($elem, $inputData);
}
}
/* now we have $inputData in nice format like
* parent(child, child, child(child, child(child, child)), child(child(child(child)))),
* parent(child, child, child(child, child(child, child)), child(child(child(child))))
* */
$inputData = merge_children_recursively(array_reverse($inputData));
function merge_children_recursively($inputData) {
$children = array();
foreach ($inputData as $row) {
if (isset($row['children'])) {
/* this ksort call is necessary because the key is actually section_position */
ksort($row['children']);
$rowCopy = $row;
unset($rowCopy['children']);
$children[] = $rowCopy;
$children = array_merge($children, merge_children_recursively($row['children']));
} else {
$children[] = $row;
}
}
return $children;
}
function put_in_parent($elem, $inputData) {
foreach ($inputData as $k => $row) {
if ($row['section_id'] == $elem['section_parent']) {
if (!isset($inputData[$k]['children'])) {
$inputData[$k]['children'] = array();
}
$inputData[$k]['children'][$elem['section_position']] = $elem;
break;
}
}
return $inputData;
}
function array_orderby() {
$args = func_get_args();
$data = array_shift($args);
foreach ($args as $n => $field) {
if (is_string($field)) {
$tmp = array();
foreach ($data as $key => $row) {
$tmp[$key] = $row[$field];
}
$args[$n] = $tmp;
}
}
$args[] = &$data;
call_user_func_array('array_multisort', $args);
return array_pop($args);
}
echo '<pre>' . print_r($inputData, true) . '</pre>';
exit;
I did remove some stuff from the input data so I could orient myself. Just try to give your input data to the logic and let me know what is the result.

How to generate a tree-like array from flat array without use of references

I'm stuck with transforming flat array to multidimensional tree like. I have already done it, but I used references, which creates another set of problems down the line, so I need to do this without references.
Input array:
Array
[
1 =>[
'content_id' => 1,
'sort_order' => 1,
'level' => 1
],
2 =>[
'content_id' => 7,
'sort_order' => 2,
'level' => 2
],
3 =>[
'content_id' => 4,
'sort_order' => 3,
'level' => 2
],
4 =>[
'content_id' => 2,
'sort_order' => 4,
'level' => 3
],
5 =>[
'content_id' => 3,
'sort_order' => 5,
'level' => 1
],
6 =>[
'content_id' => 6,
'sort_order' => 6,
'level' => 1
],
7 =>[
'content_id' => 5,
'sort_order' => 7,
'level' => 2
]
]
Output array:
1 => [
'id' = 1,
'visited' = 0,
'children' => [
2 => [
'id' => 7,
'visited' => 0,
'children' => []
],
3 => [
'id' => 4,
'visited' => 0,
'children' => [
4 => [
'id' = 2,
'visited' = 0,
'children' => []
]
]
],
5 => [
'id' => 3,
'visited' => 0,
'children' => []
],
6 => [
'id' => 6,
'visited' => 0,
'children' => [
7 => [
'id' => 5,
'visited' => 0,
'children => []
]
]
]
Any idea how to tackle a problem like this without having direct parent relation set? I can use recursion, but references are problem.
Oooh, this kind of problems do tickle my fancy. So, here is my solution:
<?php
$origArray = array(
array('content_id' => 1, 'sort_order' => 1, 'level' => 1),
array('content_id' => 7, 'sort_order' => 2, 'level' => 2),
array('content_id' => 4, 'sort_order' => 3, 'level' => 2),
array('content_id' => 2, 'sort_order' => 4, 'level' => 3),
array('content_id' => 3, 'sort_order' => 5, 'level' => 1),
array('content_id' => 6, 'sort_order' => 6, 'level' => 1),
array('content_id' => 5, 'sort_order' => 7, 'level' => 2),
);
function sortByOrder($a, $b) {
if ($a['sort_order'] == $b['sort_order']) {
return 0;
}
return ($a['sort_order'] < $b['sort_order']) ? -1 : 1;
}
function createHierarchicalArray($arr) {
$result = array();
foreach ($arr as $el) {
$result = insertArrayElement($result, $el['content_id'], $el['level']);
}
return $result;
}
function insertArrayElement($array, $id, $level, $currentLevel = 1) {
if ($level > $currentLevel) {
$ids = array_keys($array);
$currentId = end($ids);
if (!isset($array[$currentId]['children'])) {
$array[$currentId]['children'] = array();
}
$array[$currentId]['children'] = insertArrayElement($array[$currentId]['children'], $id, $level, $currentLevel + 1);
} else {
$array[$id] = array();
}
return $array;
}
// Could do without this, if the array is already sorted. Otherwise it's a necessary step.
uasort($origArray, 'sortByOrder');
$result = createHierarchicalArray($origArray);
var_dump($result);
Edit: Changed the code to incorporate the changes in the question.

Categories