我在 .csv 文件中有一个树结构(节点是文本类型),在读取 csv 之后,我想将数据存储在 ruby 对象中。我浏览了一些树插件,我认为nested_set 会为我服务。但是,我在修复 csv 文件格式时遇到问题,以便我可以读取它并转换为树对象。是否有任何直接的方法可以将 csv 文件或二维数组转换为树数据结构?
问问题
1215 次
2 回答
2
在您澄清不需要将此树存储在数据库中之后,我建议丢弃 NestedSets(它们用于在 RDBMS 上存储嵌套的对象集,您不需要)。你需要什么我简单的树
class Node
attr_accessor :parent, :children, :text
def initialize(text)
@text = text
@children = []
end
end
因为我有权选择 CSV 文件的格式,所以我建议这样:
id,parent,text
1,,"1"
2,1,"1.1"
3,1,"1.2"
3,2,"1.1.1"
树根是第一行,没有父级,并且总是有父级在其子级之前声明的顺序。这样你就可以建立树
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"]
如果您需要从子节点获取所有文本,那么您需要使用更多技巧
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"]
于 2009-12-15T12:55:11.063 回答
1
看来您根本不需要使用 ORM。你为什么不自己做你的树逻辑,用像 Ruby 这样的动态语言,这很容易:
require 'set'
# expects an array of [parent, child] pairs, returns the root element of a tree
def make_tree a
tree = {}
a.each do |p, c|
tree[p] ||= {:value => p}
tree[p][:children] ||= Set.new
tree[c] ||= {:value => c}
tree[c][:parent] = tree[p]
tree[p][:children] << tree[c]
end
tree.values.find{|e| e[:parent].nil?}
end
root = make_tree [[1,2],[3,4],[1,3],[4,5]]
puts root.inspect
puts root[:value]
或者,如果你想要更多的 OO,你可以使用TreeNode
class 而不是Hash
above。
哦,如果您需要通过键直接访问特定的树节点(在本例中为整数值本身),请将方法更改为返回tree
哈希而不是仅返回根元素。
于 2009-12-15T14:14:24.827 回答