Tree view hierarchy

P

Patrick Spence

Tree view displayed on web page looks like this:

Smoking
Survey & Feedback
Depression
Survey & Feedback
Stress Management
Survey & Feedback
Weight Management
Exercise
Survey & Feedback
Healthy Eating
Survey & Feedback
Managing Emotions
Survey & Feedback

Using the "className" property of each node, I am able to
determine the hierarchy. After scraping the list of nodes
from the page, I have an array that contains the following:

[
[ 1, "Smoking", "root" ],
[ 2, "Survey & Feedback", "leaf" ],
[ 3, "Depression", "root" ],
[ 4, "Survey & Feedback", "leaf" ],
[ 5, "Stress Management", "root" ],
[ 6, "Survey & Feedback", "leaf" ],
[ 7, "Weight Management", "root" ],
[ 8, "Exercise", "parent" ],
[ 9, "Survey & Feedback", "leaf" ],
[10, "Healthy Eating", "parent" ],
[11, "Survey & Feedback", "leaf" ],
[12, "Managing Emotions", "parent" ],
[13, "Survey & Feedback", "leaf" ]
]

What I need to do is iterate thru each element of the array,
determining the parent and root nodes of each element,
separating each level of the hierarchy with a pipe symbol.
The end result would be an array that contains something
like this:

[
["Smoking|Survey & Feedback"]
["Depression|Survey & Feedback"]
["Stress Management|Survey & Feedback"]
["Weight Management|Exercise|Survey & Feedback"],
["Weight Management|Healthy Eating|Survey & Feedback"],
["Weight Management|Managing Emotions|Survey & Feedback"]
]

Anyone got any ideas on this?

TIA
 
B

Bira

What I need to do is iterate thru each element of the array,
determining the parent and root nodes of each element,
separating each level of the hierarchy with a pipe symbol.
The end result would be an array that contains something
like this:

Here's something that might help. This code buils an actual tree,
keeping track of the leaves, and lets the Node class worry about
printing the correct names. The output needs to be tweaked a little if
you want nested arrays, but it's basically correct:


============

class Node
def initialize(value, parent=nil, children=[])
@value = value
@parent = parent
@children = children
end

def to_s
if @parent.nil?
@value
else
@parent.to_s + "|" + @value
end
end

def add_child(node)
node.parent = self
@children << node
end

attr_accessor :parent
end

array =
[
[ 1, "Smoking", "root" ],
[ 2, "Survey & Feedback", "leaf" ],
[ 3, "Depression", "root" ],
[ 4, "Survey & Feedback", "leaf" ],
[ 5, "Stress Management", "root" ],
[ 6, "Survey & Feedback", "leaf" ],
[ 7, "Weight Management", "root" ],
[ 8, "Exercise", "parent" ],
[ 9, "Survey & Feedback", "leaf" ],
[10, "Healthy Eating", "parent" ],
[11, "Survey & Feedback", "leaf" ],
[12, "Managing Emotions", "parent" ],
[13, "Survey & Feedback", "leaf" ]
]


leaves = []


last_root = nil
last_parent = nil

array.each do |current|

if ( current[2] == 'root')

last_root = Node.new(current[1])

elsif ( current[2] == 'parent' )

last_parent = Node.new(current[1])
last_root.add_child(last_parent)

elsif ( current[2] == 'leaf' )

leaves << Node.new(current[1])
( last_parent || last_root ).add_child( leaves.last )

end

end

puts leaves.join("\n")
 
T

Tom Pollard

What I need [is] an array that contains something like this:

[
["Smoking|Survey & Feedback"]
["Depression|Survey & Feedback"]
["Stress Management|Survey & Feedback"]
["Weight Management|Exercise|Survey & Feedback"],
["Weight Management|Healthy Eating|Survey & Feedback"],
["Weight Management|Managing Emotions|Survey & Feedback"]
]

First, if I was faced with this, I'd create a real tree structure, as
Bira showed you, and generate the above list from that. If you need
to do anything more than this example, or if there could be multiple
levels of parent nodes, then a real tree would be much easier to use.

On the other hand, if you really just need that result, and the
structure of your menu isn't ever going to have more than one parent
level, you could also do something like the following:

nodes = [
[ 1, "Smoking", "root" ],
...
[13, "Survey & Feedback", "leaf" ]
]

root = []
parent = []
leaves = []
nodes.each do |node|
idx, title, type = *node
case type
when 'root'
root = [ title ]
parent = []
when 'parent'
parent = [ title ]
when 'leaf'
leaves << (root + parent + [title]).join('|')
end
end

At the end, 'leaves' will hold the list you wanted.

Cheers,

TomP
 
P

Patrick Spence

On the other hand, if you really just need that result, and the
structure of your menu isn't ever going to have more than one parent
level, you could also do something like the following:
<snip>
Unless I misunderstood... the Weight Management "root" node has
multiple "parent" level nodes. So, with that said, it would appear that
Bira's solution fits the bill.

Thanks again chaps!
 
T

Tom Pollard

<snip>
Unless I misunderstood... the Weight Management "root" node has
multiple "parent" level nodes.

It has multiple 'parent' nodes, but only one parent level. The
snippet I provided handles that. However, if a parent could contain
one or more lower-level parents, rather than just leaves, then my
code wouldn't work correctly anymore. (You could adapt it, easily
enough, as long as each level was clearly labeled by type, but better
to have general solution.)

TomP
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,813
Latest member
lawrwtwinkle111

Latest Threads

Top