Skip to content

Instantly share code, notes, and snippets.

@kcrwfrd
Created June 18, 2014 15:48
Show Gist options
  • Save kcrwfrd/ed6f7eed1343ef0a4686 to your computer and use it in GitHub Desktop.
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
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