1

.csvファイルにツリー構造があり(ノードはテキストタイプです)、csvを読み取った後、データをrubyオブジェクトに保存します。私はいくつかのツリープラグインを試しましたが、nested_setが私にとっての目的に役立つと思います。しかし、csvファイルの形式を修正して、それを読み取ってツリーオブジェクトに変換できるようにするという問題に直面しています。csvファイルまたは2次元配列をツリーデータ構造に変換する直接的な方法はありますか?

4

2 に答える 2

2

このツリーをデータベースに保存する必要がないことを明確にした後、NestedSetsを破棄することをお勧めします(ネストされたオブジェクトのセットをRDBMSに保存する必要がありますが、これは必要ありません)。必要なもの私は単純な木

class Node
  attr_accessor :parent, :children, :text

  def initialize(text)
    @text = text
    @children = []
  end
end

CSVファイルの形式を選択する権利があるので、次のようにsthをお勧めします。

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の代わりにクラスを作成できますHash

ああ、特定のツリーノードにキー(この場合は整数値自体)で直接アクセスする必要がある場合はtree、ルート要素だけでなくハッシュを返すようにメソッドを変更します。

于 2009-12-15T14:14:24.827 に答える