Created
June 18, 2014 15:48
-
-
Save kcrwfrd/ed6f7eed1343ef0a4686 to your computer and use it in GitHub Desktop.
Creates a node tree from a flat array of objects with `path` attributes
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
animals = [ | |
name: 'Labrador' | |
path: ['Animals', 'Dogs', 'Labrador'] | |
, | |
name: 'Poodle' | |
path: ['Animals', 'Dogs', 'Poodle'] | |
, | |
name: 'Cheetah' | |
path: ['Animals', 'Cats', 'Cheetah'] | |
, | |
name: 'Lion' | |
path: ['Animals', 'Cats', 'Lion'] | |
] | |
humans = [ | |
name: 'Matt Damon' | |
path: ['Humans', 'Famous', 'Matt Damon'] | |
, | |
name: 'Myself' | |
path: ['Humans', 'Other', 'Myself'] | |
] | |
sentient_beings = [].concat animals, humans | |
# Create a function that returns this expected output | |
expected = [ | |
name: 'Animals', | |
children: [ | |
name: 'Dogs', | |
children: [ | |
name: 'Labrador' | |
, | |
name: 'Poodle' | |
] | |
, | |
name: 'Cats', | |
children: [ | |
name: 'Cheetah' | |
, | |
name: 'Lion' | |
] | |
] | |
, | |
name: 'Humans' | |
children: [ | |
name: 'Famous' | |
children: [ | |
name: 'Matt Damon' | |
path: ['Humans', 'Famous', 'Matt Damon'] | |
] | |
, | |
name: 'Other' | |
children: [ | |
name: 'Myself' | |
path: ['Humans', 'Other', 'Myself'] | |
] | |
] | |
] | |
getTree = (array) -> | |
# First, iterate over targets | |
_.reduce array, (tree, target) -> | |
# Next, we iterate over the current target's path. On each iteration, | |
# we will travel down to the child node that matches the current path, | |
# creating it if necessary. | |
_.reduce target.path, (node, name, index) -> | |
# We've reached the terminus, exit | |
return unless node.children | |
# Return the child node for the current path if it already exists | |
childNode = _.find node.children, (child) -> | |
return child.name is name | |
# If the child node doesn't exist yet, let's create it | |
unless childNode | |
childNode = {name} | |
if index is target.path.length - 1 | |
# This child node is the terminus, add the target data | |
_.extend childNode, target | |
else | |
# This child node is a branch with its own children | |
childNode.children = [] | |
node.children.push childNode | |
# Returns the childNode for the next iteration to consume, | |
# so that we may travel down the path tree | |
return childNode | |
, tree | |
# Target added, return the tree so we can add the next target to it | |
return tree | |
, | |
children: [] | |
tree = getTree sentient_beings | |
console.log tree |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment