I have a history with having tree issues and I've done a lot of research on the topic. I think maybe I'm using the wrong hammer on this nail.
I am trying to create a tree hierarchy data set from an array, but not just one that has defined parent-child relationships. It's pretty much comparing one array in the data set to another, and then combining what is the same, and branching the differences into a new array.
The reasoning behind this is for searching against the data sets later (such as ACL) which are expected to be large, and to return this format through API calls.
Coming from a PHP and MySQL query, I return an array that looks like this (the key value pairs could be anything, this is just a generalization):
$testArray = array(
array('group' => 'Group1','group_id' => '1','portal' => 'Portal1','portal_id' => '1','role' => 'Role1','role_id' => '1','permission' => 'Permission1','permission_id' => '1'),
array('group' => 'Group1','group_id' => '1','portal' => 'Portal1','portal_id' => '1','role' => 'Role1','role_id' => '1','permission' => 'Permission2','permission_id' => '2'),
array('group' => 'Group1','group_id' => '1','portal' => 'Portal2','portal_id' => '2','role' => 'Role1','role_id' => '1','permission' => 'Permission3','permission_id' => '3'),
array('group' => 'Group1','group_id' => '1','portal' => 'Portal2','portal_id' => '2','role' => 'Role2','role_id' => '2','permission' => 'Permission1','permission_id' => '1'),
array('group' => 'Group2','group_id' => '2','portal' => 'Portal1','portal_id' => '1','role' => 'Role3','role_id' => '3','permission' => 'Permission1','permission_id' => '1'),
array('group' => 'Group2','group_id' => '2','portal' => 'Portal1','portal_id' => '1','role' => 'Role3','role_id' => '3','permission' => 'Permission2','permission_id' => '2')
);
Pseudo Output After:
(Group_Name = Group1, Group_ID = 1)
(Portal_Name = Portal1, Portal_id = 1) (Portal_Name = Portal2, Portal_id = 2)
(Role,RoleID) (Role,RoleID)
(Permission,Permission_id) (Permission,Permission_id)
Here's the WIP function. It's a little all over the place ATM, but this is where my head is at:
//List of keyList to compare against
if(is_array($testArray[0])) {
$keyList = array_keys($testArray[0]);
}
function buildTree(&$data, $keyList) {
$branch = array();
$tree = array();
foreach($keyList as $k => &$keyName) {
//Each row in the data set is an array
foreach($data as $rowKey => &$rowArraySet) {
//If the branch key exists, and matches
if(isset($rowArraySet[$keyName]) && isset($keyList[$keyName]) &&
isset($branch[$keyList[$keyName]][$rowArraySet[$keyName]])) {
if(isset($data[1+$rowKey]) &&
$rowArraySet[$keyName] == $data[1+$rowKey][$keyName]) {
$branch[$keyName][$rowArraySet[$keyName]] = array_diff($rowArraySet, $rowArraySet[$keyName]);
unset($data[$rowKey]);
}
}
//If the branch does not exist, and matches next array record
else if(isset($data[1+$rowKey]) &&
$rowArraySet[$keyName] == $data[1+$rowKey][$keyName]) {
$branch[$keyName] = array();
$branch[$keyName][$rowArraySet[$keyName]] = array_diff($rowArraySet, array($keyName => $rowArraySet[$keyName]));
unset($data[$rowKey]);
}
//Create new branch key (no match)
else if(isset($rowArraySet[$keyName])) {
$branch[$keyName] = array();
$branch[$keyName][$rowArraySet[$keyName]] = array_diff($rowArraySet, array($keyName => $rowArraySet[$keyName]));
unset($data[$rowKey]);
}
echo $rowKey;
}
//Remove keyName from checking
unset($keyList[$k]);
//Compare branch
//$tree[] = buildTree($branch, &$keyList);
//echo '<pre>';
//var_dump($branch);
//die;
}
return $tree;
}
Yes, I know there's a little place in hell for programmers and undocumented code. My thinking goes like this:
- Capture Keys from the first array in the set (this is the parent - child like relationship, at least the order to check against)
- Use the keys to compare each array to eachother in the set (if exists/set etc)
- Matching values create a new branch and move the array over, combining them
- Check the next set, and check to see if the keys exist in the branch
- Recursively sort the branch once complete
- Return branch to tree array and output tree
As always, any guidance is appreciated. I feel like I'm close to figuring this out, I just can't wrap my head around it. Thank you.
Edit per recommendations.