I recently started using JSTREE to display my json data (I am showing it as an array in my sample code here). But, some of the nodes are repeating. I was thinking of adding an If loop to check if the node is already a child node but not sure how to do that. I also think my code is also not very well performing because of the many for loops. I am a PHP newbie so not sure if there might be a faster way to recurse through an array. Here is my code.
$relation = array(
"parent"=>array("item"=>array("cs","ls")),
"cs"=>array("item"=>array("cs_1")),
"ls"=>array("item"=>array("ls_1")),
"cs_1"=>array("item"=>array("cs_1_1"))
);
$tree = array();
$i=0;
foreach($relation as $key_parent=>$value_parent) {
#$children = array_keys($value_parent);
$tree[$i++] = array('id'=>$key_parent,'text'=>$key_parent,'state'=>array('opened'=>true),'parent'=>'#');
foreach($value_parent['item'] as $key_child_1=>$value_child_1) {
$tree[$i++]= array('id'=>$value_child_1,'text'=>$value_child_1,'state'=>array('opened'=>true),'parent'=>$key_parent);
}
}
Your input structure is far from optimal, but it can still work. If I understand correctly, this is what you need:
$relation = array(
"parent"=>array("item"=>array("cs","ls")),
"cs"=>array("item"=>array("cs_1")),
"ls"=>array("item"=>array("ls_1")),
"cs_1"=>array("item"=>array("cs_1_1"))
);
$tree = array();
foreach($relation as $key_parent=>$value_parent) {
$tree[$key_parent] = array('id'=>$key_parent,'text'=>$key_parent,'state'=>array('opened'=>true),'parent'=>'#');
foreach($value_parent['item'] as $key_child_1=>$value_child_1) {
$tree[$value_child_1]= array('id'=>$value_child_1,'text'=>$value_child_1,'state'=>array('opened'=>true),'parent'=>$key_parent);
}
}
$tree = array_values($tree);
The only fix is using the actual node ID as a key in the $tree array, and then calling array_values to convert it back.
Related
Any idea on how to restructure the json below:
$jsonArray = [{"Level":"77.2023%","Product":"Milk","Temperature":"4"},
{"Level":"399.2023%","Product":"Coffee","Temperature":"34"},
{"Level":"109.2023%","Product":"Chocolate","Temperature":"14"}]
Expected outcome:
$expected = {"Milk":{"Level":"77.2023%","Temperature":"4"},
"Coffee":{"Level":"399.2023%","Temperature":"34"},
"Chocolate":{"Level":"109.2023%","Temperature":"14"}
}
I'm new and my thinking is get the product value in array and again use foreach loop to find the others value? .
Here's one possibility:
$jsonArray = '[{"Level":"77.2023%","Product":"Milk","Temperature":"4"},
{"Level":"399.2023%","Product":"Coffee","Temperature":"34"},
{"Level":"109.2023%","Product":"Chocolate","Temperature":"14"}]';
$output = array();
foreach (json_decode($jsonArray, true) as $row) {
$product = $row['Product'];
$output[$product] = $row;
unset($output[$product]['Product']);
}
echo json_encode($output);
Output:
{"Milk":{"Level":"77.2023%","Temperature":"4"},
"Coffee":{"Level":"399.2023%","Temperature":"34"},
"Chocolate":{"Level":"109.2023%","Temperature":"14"}
}
Demo on 3v4l.org
This made some trick
$a = '[{"Level":"77.2023%","Product":"Milk","Temperature":"4"},
{"Level":"399.2023%","Product":"Coffee","Temperature":"34"},
{"Level":"109.2023%","Product":"Chocolate","Temperature":"14"}]';
$newAr = array();
foreach(json_decode($a,true) as $key=>$value)
{
$newAr[$value['Product']] = array(
'Level' => $value['Level'],
'Temperature' => $value['Temperature'],
);
}
There are many ways to perform this with Loops in PHP. Other answers demonstrate it accurately. I would also suggest to integrate some form of Error handling, data validation/filtering/restriction in your code to avoid unexpected results down the road.
For instance, json_decode(), either assigned to a variable pre-foreach or straight in the foreach() 1st argument will just raise a warning if the original json is not valid-json, and just skip over the foreach used to construct your final goal. Then if you pass the result (that may have failed) directly to your next logic construct, it could create some iffy-behavior.
Also, on the concept of data-validation & filtering, you could restrict the foreach(), or any other looping mechanism, to check against a Product_List_Array[Milk,Coffee,Chocolate], using if(in_array() ...) so the final/goal object only contains the expected Products, this, in the case the original json has other artifacts. Filtering the values can also increase stability in restricting, for example, Temperature to Float.
I'm having a hard time trying to write a traversing function that outputs a child-node's parent-nodes.
Take a look at the example b-tree
Here is the sample dataset I'm using:
$nodes = array(
array('f','b'),
array('f','g'),
array('b','a'),
array('b','d'),
array('g','i'),
array('d','c'),
array('d','e'),
array('i','h')
);
I'm trying to output a results array that contains all child node arrays which contain parent associations.
Example Outputs:
node(d)'s parents are (b,f)
node(c)'s parents are (d,b,f)
node(h)'s parents are (i,g,f)
I can't figure out how to traverse past the direct parent node.
foreach($nodes as $node){
//CHECK IF NODE EXISTS
if(array_key_exists($node[1],$results)){
//DO NOTHING
array_push($results[$node[1]],$node[0]);
}
else{
//CREATE NEW CHILD ARRAY
$results[$node[1]] = [];
//PUSH PARENT INTO CHILD ARRAY
array_push($results[$node[1]],$node[0]);
}
}
foreach($results as $k => $v){
echo "child[$k] parents(" . implode($v,', ').")" ;
echo "</br>";
}
Question: How can I achieve this output in the most efficient manor?
The best way to deal with such cases is to use recursive functions.
echo findParents('h',$nodes);
function findParents($find,$btree){
$parents;
foreach($btree as $node){
if($node[1]===$find){
$parents .=$find.',';
return $parents .= findParents($node[0], $btree);
}
}
return $find;
}
Check the live code here: https://www.tehplayground.com/ElTdtP61DwFT1qIc
The only drawback is that it would return the original node in the return list. But I think you can live with that.
I think the better representation of the tree would be:
$nodes = array(
'f'=>array('d','g'),
'b'=>array('a','d'),
'g'=>array('i'),
'd'=>array('c','e'),
'i'=>array('h')
);
But that would need slight modification to the above code.
To get an array as the response:
function findParentsArray($find,$btree){
$parentsArray = explode(',',findParents($find,$btree));
array_shift($parentsArray);
return $parentsArray;
}
It should be possible to have that done directly in findParents() but I don't have time to look into it now.
I have this current structure:
{"resultset":[
{"IM":[2],"SR":[2],"TA":[4],"PMT":[2],"IMT":[2]},
{"IM":[1],"SR":[0],"TA":[4],"PMT":[1],"IMT":[0]},
{"IM":[2],"SR":[5],"TA":[17],"PMT":[2],"IMT":[5]}
]
}
I need to generate a foreach loop (I think) searching an each key and transforming the structure to look like this instead:
{"resultset":[ {"IM":[2,1,2],"SR":[2,0,5],"TA":[4,4,17],"PMT":[2,1,2],"IMT":[2,0,5]} ]}
I know I have to use a foreach loop and search on the key and then push the data back into a new array with this structure. but im having difficulty getting my head around it. any help would be appreciated.
I might need to change my strategy here:
this is my current code that is generated the first array:
for($i=0; $i<sizeof($teams);$i++)
{
$openResultSet['resultset'][] = $DAL->runGenericSQL(TotalTicketsInQueue($teams[$i]),"open",$i);
}
this calls the following (in a nutshell)
while ($row = odbc_fetch_array($resultSet))
{
$OpenTicketResultArray["IM"][] = intval($row["IM"]);
$OpenTicketResultArray["SR"][] = intval($row["SR"]);
$OpenTicketResultArray["TA"][] = intval($row["TA"]);
$OpenTicketResultArray["PMT"][] = intval($row["IM"]);
$OpenTicketResultArray["IMT"][] = intval($row["SR"]);
}
return $OpenTicketResultArray;
I'm thinking at each iteration when the first array comes back store the results in a new key'd array and then continue to push the new results. but I'm new to this :(
Hi guys I found similar problems to this already answered but any of them was the same of my situation.
I have a loop iterating a mysql data object and I'd like to construct a multidimensional array based on all the results, but for instance, if I do this:
$i=0;
while($row3 = mysql_fetch_array($raw_result, MYSQL_ASSOC)){
$row2[0] = array('father'+.$i => $children);
$i++;
}
It only keeps the last child (and his father). And if I do this:
while($children = mysql_fetch_array($raw_result, MYSQL_ASSOC)){
$myData[0] = array('father1' => $children, 'father2' => $children);
}
Then it works fine, it keeps both fathers, but obviously this won't work dynamically because each iteration overwrites the last one.
So is there a way to append this data instead of overwrite it?
Thank you so much for your time!
Change to
$row2[] = array('father'.$i => $children);
or to
$row2['father'.$i] = $children;
I have a menu structure (Drupal) that contains elements representing a menu link. If the menu has a child menu (is the parent of a submenu) it has an array key 'below' with a menu item inside with the same structure. In theory this menu could be infinitely deep and the only way that I know how to go through each level is by create a new loop on the item if 'below' has anything in it. I know there has to be a more elegant and dynamic way to deal with this. I'm not really looking for a Drupal specific answer as this problem has come up before and I've just hacked it together. Thanks for reading!
Without an example of the kind of data you're working with it's difficult to give an exact implementation, but the general class of problems you describe is one that can usually be solved with recursion - a function that calls itself.
<?php
function deepPrintArr (array $arr)
{
$output = '';
foreach ($arr as $elem)
{
if (is_array $elem)
{
$output .= deepPrintArr ($elem);
}
else
{
$output .= "<p>$elem</p>\n";
}
}
return ($output);
}
echo (deepPrintArr ($some_deeply_nested_array));
?>
Please take time to "read" /inc/menu.inc in your drupal code.
This file contains a host of very usefull functions, some are not mentioned in any documentation.
menu_get_active_trail() for example gives you the current active path for the active page. This is a lot easier than looping recursive through all menu items in your own code.
For this site: Qrios I wrote some code to build a two level menu in Drupal:
<?php $base_tree = menu_tree_page_data($use_menu);
//Debug
//print_r($tree);
foreach ($base_tree as $item) {
if ($item['link']['in_active_trail'] == 1){
$tree = $item['below'];
}else{
$tree = array(); //empty array
}
} ?>
Not sure if this is what you mean, but you get the idea of using Drupals functions. You just have to find them.