I have a tree structure in a .csv file (nodes are of type text), and after reading the csv i want to store the data in a ruby object. I went through a few tree plugins and i think nested_set would serve the purpose for me. However, i am facing problem with fixing a format of csv file, so that i can read it and convert into tree object. Is there any direct way of converting a csv file or 2 dimensional array, into a tree data structure??
After you clarified that you don't need to store this tree in database, I suggest to throw away NestedSets (they're to store nested sets of objects on RDBMS, which you don't need). What you need i simple tree
class Node
attr_accessor :parent, :children, :text
def initialize(text)
@text = text
@children = []
end
end
As I have right to choose format of CSV file, then I suggest sth like this:
id,parent,text
1,,"1"
2,1,"1.1"
3,1,"1.2"
3,2,"1.1.1"
Tree root is first row, without parent, and there is always order that parent is declared before its children. That way you can build tree
def build_tree(rows)
nodes = {}
rows.each do |row|
node = Node.new(row[:text])
nodes[row[:id]] = node
node.parent = nodes[row[:parent]]
nodes[row[:parent]].children << node if row[:parent]
end
nodes.values.find {|node| node.parent.nil? }
end
root = build_tree(rows)
root.text #=> "1"
root.children.map(&:text) #=> ["1.1", "1.2"]
root.children[0].children.map(&:text) #=> ["1.1.1"]
If you need to get all texts from subnodes, then you need to use more tricks
def get_nodes(tree_node)
[ tree_node, tree_node.children.map{|node| get_nodes(node)} ].flatten
end
get_nodes(root).map(&:text) #=> ["1", "1.1", "1.1.1", "1.2"]