I am looking to convert a multi dimensional array into another multidimensional array using a recursive function.
Source array :
Array
(
[1] => Array
(
[id] => 1
[source_name] => kk56ca1d0f2378f
[company_id] => 1
[lft] => 1
[rgt] => 18
[parent_id] => 0
[children] => Array
(
[2] => Array
(
[id] => 2
[source_name] => kk56ca1d17f3f63
[company_id] => 1
[lft] => 2
[rgt] => 3
[parent_id] => 1
[children] => Array
(
)
)
[3] => Array
(
[id] => 3
[source_name] => kk56ca1d1ebe975
[company_id] => 1
[lft] => 4
[rgt] => 13
[parent_id] => 1
[children] => Array
(
[6] => Array
(
[id] => 6
[source_name] => kk56ca1fc882ac0
[company_id] => 1
[lft] => 5
[rgt] => 10
[parent_id] => 3
[children] => Array
(
)
)
)
)
)
)
)
which I need to get into the format of
Array
(
[0] => Array
(
[id] => 1
[text] => kk56ca1d0f2378f
[parent_id] => 0
[nodes] => Array
(
[0] => Array
(
[id] => 2
[text] => kk56ca1d17f3f63
[parent_id] => 1
[nodes] => Array
(
)
)
[1] => Array
(
[id] => 3
[text] => kk56ca1d1ebe975
[parent_id] => 1
[nodes] => Array
(
[0] => Array
(
[id] => 6
[text] => kk56ca1fc882ac0
[parent_id] => 3
[nodes] => Array
(
)
)
[1] => Array
(
[id] => 15
[text] => kk
[parent_id] => 3
[nodes] => Array
(
)
)
)
)
)
)
)
I have been trying for hours and getting nowhere with this. Any help would be really appreciated.
The source array has associative indexes (though they are numbers) and the destination array has numerical indexes. Besides this, just need to remove a few indexes and change names of a few.
EDIT :
Specific changes :
change index name source_name to text
change index name children to nodes
unset indexes lft, rgt, company_id
I do not have much experience with recursion so I have trying fruitlessly.
This is what I could come up with :
// pass array of nodes
function convert_array($from){
// this is a node
if(isset($from['source_name']))
{
$temp = array();
$temp['id'] = $from['id'];
convert_array($from['children']);
}
// this is an array of nodes
else
{
foreach($from as $arr)
{
$ret = convert_array($arr);
print_r($ret);
}
}
}
But I am not able to understand what data to be returned and how the new array builds up from the return values.
Here the working function:
function convert_array( $array )
{
$retval = array();
foreach( $array as $row )
{
$child = array();
$child['id'] = $row['id'];
$child['text'] = $row['source_name'];
$child['parent_id'] = $row['parent_id'];
if( count( $row['children'] ) )
{ $child['nodes'] = convert_array( $row['children'] ); }
else
{ $child['nodes'] = array(); }
$retval[] = $child;
}
return $retval;
}
3v4l demo
I think it is self-explanatory, BTW: we init an empty array ($retval), then we perform a foreach loop through all array argument: for each element, we init a new array and we add it id, source_name as text and parent_id; if the children index has elements, we perform a recursive call to fill nodes array index, otherwise we set it to empty array.
Related
I want to break the below nested array in simple associative array.
Input
Array
(
[0] => Array
(
[id] => 1
[name] => Gadgets
[code] => gadget
[parent_id] =>
[children] => Array
(
[0] => Array
(
[id] => 2
[name] => Mobile
[code] => mobile
[parent_id] => 1
[children] => Array
(
)
)
[1] => Array
(
[id] => 3
[name] => Laptops
[code] => laptop
[parent_id] => 1
[children] => Array
(
[0] => Array
(
[id] => 4
[name] => Dell
[code] => dell
[parent_id] => 3
[children] => Array
(
)
)
[1] => Array
(
[id] => 5
[name] => Lenovo
[code] => lenovo
[parent_id] => 3
[children] => Array
(
)
)
)
)
)
)
)
Output
Array
(
[0] => Array
(
[id] => 1
[name] => Gadgets
[code] => gadget
[parent_id] =>
)
[1] => Array
(
[id] => 2
[name] => Mobile
[code] => mobile
[parent_id] => 1
)
[2] => Array
(
[id] => 3
[name] => Laptops
[code] => laptop
[parent_id] => 1
)
[3] => Array
(
[id] => 4
[name] => Dell
[code] => dell
[parent_id] => 3
)
[4] => Array
(
[id] => 5
[name] => Lenovo
[code] => lenovo
[parent_id] => 3
)
)
Need help in making this type of array from the given array. I tried many things with for loops, but get stuck when in case there are many nested array and that solution does not fit correctly to my requirement.
There is one root node and others are child nodes and many parent nodes can have child nodes.
There are a ton of ways to do this, here are a couple of simple examples. If you don;t care about maintaining order, the recursive function is pretty simple. If you do need to maintain the order of the elements as they are encountered while traversing the tree (to render them as tables for example), it's just a bit more of a faff.
<?php
function flattenTree($array)
{
$output = [];
foreach($array as $currBranch)
{
if(!empty($currBranch['children']))
{
$children = flattenTree($currBranch['children']);
$output = array_merge($output, $children);
}
unset($currBranch['children']);
$output[] = $currBranch;
}
return $output;
}
function flattenTreeMaintainingOrder($array)
{
$output = [];
foreach($array as $currBranch)
{
$children = (array_key_exists('children', $currBranch)) ? $currBranch['children']:[];
unset($currBranch['children']);
$output[] = $currBranch;
if(!empty($children))
{
$children = flattenTreeMaintainingOrder($children);
$output = array_merge($output, $children);
}
}
return $output;
}
$flat = flattenTree($array);
$flatOrdered = flattenTreeMaintainingOrder($array);
print_r($flat) . PHP_EOL;
print_r($flatOrdered) . PHP_EOL;
A recursive function is one option...
function extractChildren($parent, $farr) {
$children = $parent['children'];
if (!$children || count($children)==0) return $farr;
unset($parent['children']);
$farr[]= $parent;
return extractChildren($children, $farr);
}
$finalarray=array();
// $array is the array you have in your question
foreach ($array as $parent) {
$finalarray = extractChildren($parent, $finalarray);
}
As #El_Vanya mentioned above, there are scads of other ways to accomplish this here: How to Flatten a Multidimensional Array?
I have three arrays first array include ids and employees name and second array have monthly collection with employee ids and third array have daily collection with employee id and daily collection I want to merge these array with ids and name and dcollection and monthly collection but the desired output is not coming here my first array $ids is
Array
(
[0] => stdClass Object
(
[id] => 1
[name] => Rohit
)
[1] => stdClass Object
(
[id] => 2
[name] => Emop1
)
[2] => stdClass Object
(
[id] => 3
[name] => Pankaj
)
[3] => stdClass Object
(
[id] => 4
[name] => tejpal singh
)
)
second array $q1 is
Array
(
[0] => stdClass Object
(
[name] => Rohit
[id] => 1
[mcollecton] => 100
)
[1] => stdClass Object
(
[name] => Emop1
[id] => 2
[mcollecton] => 1222
)
)
third array $q2 is
Array
(
[0] => stdClass Object
(
[name] => Rohit
[id] => 1
[dcollecton] => 300
)
[1] => stdClass Object
(
[name] => Emop1
[id] => 2
[dcollecton] => 150
)
)
so far what I have tried
$new_array = array();
foreach($ids as $k) {
$q1n = array("id"=>$k->id,"name"=>$k->name);
foreach($q1 as $k1) {
if($k->id==$k1->id){
$mc = array("mc"=>$k1->mcollecton);
array_merge($q1n,$mc);
}
}
foreach($q2 as $k1){
if($k->id==$k1->id){
$dc = array("dc"=>$k1->dcollecton);
array_merge($q1n,$dc);
}
}
$a = array_merge($q1n,$mc);
$av = array_merge($q1n,$dc);
array_push($new_array,$q1n);
}
but the output is coming as
Array
(
[0] => Array
(
[id] => 1
[name] => Rohit
)
[1] => Array
(
[id] => 2
[name] => Emop1
)
[2] => Array
(
[id] => 3
[name] => Pankaj
)
[3] => Array
(
[id] => 4
[name] => tejpal singh
)
)
I want the output be like
Array
(
[0] => Array
(
[id] => 1
[name] => Rohit
[mcollection] => 100
[dcollection] => 300
)
[1] => Array
(
[id] => 2
[name] => Emop1
[mcollection] => 1222
[dcollection] => 150
)
[2] => Array
(
[id] => 3
[name] => Pankaj
[mcollection] => 0
[dcollection] => 0
)
[3] => Array
(
[id] => 4
[name] => tejpal singh
[mcollection] => 0
[dcollection] => 0
)
)
So I have tried many times but the desired output is not coming . please help me out how to get the desired output.
It seemed like that answer could be modified, or put in a function that you could call multiple times if needed to combine more than two arrays.
There's probably cleaner ways to handle this with array functions like array_merge or array_walk, but this is the general idea of how I might approach it. I haven't tested this, but maybe it's useful.
foreach($first as $key1 => $value){
foreach($second as $key2 => $value2){
// match the ids and check if array key exists on first array
if($value['id'] === $value2['id'] && empty($first[$key2])){
$first[$key][$key2] = $value2;
}
}
}
EDIT: Based on the answer you posted vs the question you asked, are you incrementing the collection numbers or just setting them? In other words why use +=? You should also be able to remove array_merge and array_push.
Below is geared more towards what you're trying to do. I haven't tested this either, but if you run into errors, post your code with the errors returned so that it's easier to debug:
foreach($ids as $k)
{
$thisArray = $newArray[] = array("id"=>$k->id,"name"=>$k->name);
foreach($q1 as $k1)
{
if($k->id == $k1->id && !empty($k1->mcollecton))
{
$thisArray['mc'] = $k1->mcollecton;
}
}
foreach($q2 as $k2)
{
if($k->id == $k2->id && !empty($k2->dcollecton))
{
$thisArray['dc'] = $k2->dcollecton;
}
}
}
// This should have both new collections fields on all array items
print_r($newArray)
code
$result = [];
foreach ($getAllAgent as $rkey => $rvalue) {
$found = -1;
for ($i = 0; $i < count($result); $i++) {
if ($result[$i]["brokerid"] == $rvalue["brokerid"]) {
$found = $i;
$result[$i]['get_agent_details'][] = $rvalue['get_agent_details']; //here to combine
break;
}
}
// if not found, create new
if ($found == -1) {
$result[] = $rvalue;
}
results
Array
(
[0] => Array
(
[id] => 2
[brokerid] => 2
[agentid] => 3
[addedby] => 1
[get_agent_details] => Array
(
[id] => 3
[name] => kenang
[ic] => 932132923
[phone] => 2313123
[0] => Array
(
[id] => 4
[name] => ivan
[ic] => 32992131
[phone] => 31231
)
)
)
)
I have one set of an array, and I loop it and restructure match the data based on ID. After that I will try to merge the same data into one array, I able add into one array. But it will not combine as one. The correct result should be as below.
[get_agent_details] => Array
(
[0] => Array(
[id] => 3
[name] => kenang
[ic] => 932132923
[phone] => 2313123
),
[1] => Array
(
[id] => 4
[name] => ivan
[ic] => 32992131
[phone] => 31231
)
)
Your problem is in this line:
$result[] = $rvalue;
Consider the case where you only have one item; this will result in:
Array
(
[0] => Array
(
[id] => 2
[brokerid] => 2
[agentid] => 3
[addedby] => 1
[get_agent_details] => Array
(
[id] => 1
[name] => Chesney Hawkes
[ic] => 932132923
[phone] => 2313123
)
)
)
But to be consistent, you need get_agent_details to be a list of items, that happens to have one entry:
Array
(
[0] => Array
(
[id] => 2
[brokerid] => 2
[agentid] => 3
[addedby] => 1
[get_agent_details] => Array
(
[0] => Array
(
[id] => 1
[name] => Chesney Hawkes
[ic] => 932132923
[phone] => 2313123
)
)
)
)
So you need to re-arrange your data, for instance by writing:
$rvalue['get_agent_details'] = [0 => $rvalue['get_agent_details']];
$result[] = $rvalue;
Then, since get_agent_details will already be a list when you encounter a second matching item, your existing code in the inner loop will do the right thing:
// Add an item to the list
$result[$i]['get_agent_details'][] = $rvalue['get_agent_details'];
I have one array which I am getting from database query response.
Now I want to count same categories and print in option_name array.
I have tried it with different array functions but want get desire output.
I have one idea to take new array and push it with foreach loop but not much idea of how can i achieve using code. Please help me to solve it.
Array
(
[0] => Array
(
[CNC] => Array
(
[id] => 5
[category_id] => 68
)
[GVO] => Array
(
[option_name] => Actors
)
)
[1] => Array
(
[CNC] => Array
(
[id] => 11
[category_id] => 72
)
[GVO] => Array
(
[option_name] => Cricketers
)
)
[2] => Array
(
[CNC] => Array
(
[id] => 3
[category_id] => 72
)
[GVO] => Array
(
[option_name] => Cricketers
)
)
[3] => Array
(
[CNC] => Array
(
[id] => 4
[category_id] => 74
)
[GVO] => Array
(
[option_name] => Musician
)
)
[4] => Array
(
[CNC] => Array
(
[id] => 7
[category_id] => 76
)
[GVO] => Array
(
[option_name] => Directors
)
)
[5] => Array
(
[CNC] => Array
(
[id] => 6
[category_id] => 76
)
[GVO] => Array
(
[option_name] => Directors
)
)
)
Desire Output:
Array
(
[Actors] => 1
[Cricketers] => 2
[Musician] => 1
[Directors] => 2
)
Thanks in advance!
You simply need to loop through the array using foreach like as
$result = [];
foreach($arr as $k => $v){
if(isset($result[$v['GVO']['option_name']])){
$result[$v['GVO']['option_name']] += 1;
}else{
$result[$v['GVO']['option_name']] = 1;
}
}
print_R($result);
You can count the option_name values by incrementing a counter in an associative array where the key is the option_name:
$counts = [];
foreach($array as $v) {
if(!isset($counts[$v['GVO']['option_name']])) {
$counts[$v['GVO']['option_name']] = 0;
}
$counts[$v['GVO']['option_name']]++;
}
print_r($counts);
Try this:
$new_arr = array();
foreach(array_column($your_arr, 'option_name') as $value){
if(in_array($value, $new_array)){
$new_array[$value] = $new_array[$value]+1;
}else{
$new_array[$value] = 1;
}
}
Output
Array
(
[Actors] => 1
[Cricketers] => 2
[Musician] => 1
[Directors] => 2
)
I have my array
Array
(
[0] => Dusche
[1] => Mobliert
)
And I have second array which is composed and looks like this:
[0] => Array
(
[id] => 1002
[attribute_id] => 65
[value_id] => 26815
[name] => Garten/-mitbenutzung
[order] => 0
)
[1] => Array
(
[id] => 1003
[attribute_id] => 65
[value_id] => 26811
[name] => Etagenheizung
[order] => 1
)
[2] => Array
(
[id] => 1004
[attribute_id] => 65
[value_id] => 26829
[name] => Balkon/Terrasse
[order] => 2
How can I search this second array with values from the first array and retrieve attribute_id from elements which have the same names?
PHP way:
filteredArray = array();
foreach ($secondArray as $type) {
if (in_array($type['name'], $firstArray)) {
$filteredArray[] = $type['attribute_id'];
}
}
Cake Set way, something along the lines of:
$filteredArray = array();
foreach ($firstArray as $keyword) {
$filteredArray = array_merge($filteredArray, Set::extract("/.[name=$keyword]/attribute_id", $secondArray));
}