Created
February 3, 2018 12:29
-
-
Save Sumurai8/a0491a3a585dd8908196c2d4868d61d6 to your computer and use it in GitHub Desktop.
Add "descendants" property to collection of nodes in nested set format with a generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Simply returns the titles of the nodes passed to it | |
* | |
* @param array $nodes Collection of nodes we want to have the titles of | |
*/ | |
function titles(array $nodes) { | |
return array_map( | |
function ($node) { | |
return $node['title']; | |
}, | |
$nodes | |
); | |
} | |
/** | |
* Generator that adds the descendants property to each node in a collection | |
* | |
* @param array $nodes pre-order walk of nodes in nested set format | |
*/ | |
function with_descendants(array $nodes) { | |
// This method of determining descendants only works if we have a continuous | |
// list of bounds. The first node should be the root node of this subtree, | |
// so if it fits "snugly" around the other nodes and we assume the nodes are | |
// in pre-order, all should be fine | |
assert( | |
(($nodes[0]['right'] - $nodes[0]['left'] - 1) / 2) === count($nodes) - 1, | |
"Cannot determine descendants when tree is not normalised" | |
); | |
// Just so we only have to process each node once to get their title | |
// we cache the titles first | |
$titles = titles($nodes); | |
// Then we run through ordered nodes | |
for ($i = 0; $i < count($nodes); $i++) { | |
// We sometimes need to access the node | |
$node = $nodes[$i]; | |
// We want to access the subtree of this node, so we calculate which | |
// node would be the first node in the subtree, and how many nodes | |
// would be in that subtree | |
$first_node = $i + 1; | |
$number_of_nodes = ($node['right'] - $node['left'] - 1) / 2; | |
// Now we take the relevant slice out of titles | |
$node['descendants'] = array_slice($titles, $first_node, $number_of_nodes); | |
// We have added our property, so we can yield the node | |
yield $node; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment