The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Building tree out of nested set

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Maxim Kulkin

Posts: 58
Nickname: hapk
Registered: Sep, 2006

Maxim Kulkin is developer in Selectosa Systems.
Building tree out of nested set Posted: Sep 14, 2009 2:06 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Maxim Kulkin.
Original Post: Building tree out of nested set
Feed Title: Software development
Feed URL: http://maximkulkin.blogspot.com/feeds/posts/full?alt=rss
Feed Description: Software development
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Maxim Kulkin
Latest Posts From Software development

Advertisement
This keeps popping up over and over again. About 2 years ago I mentioned solution on how to build tree out of nested set, but the solution was lost in google groups. I'm going to publish it here.

So, nested set: every item has LEFT and RIGHT numbers. LEFT number is less than any LEFT or RIGHT number of any descendant item. RIGHT number is greater than any LEFT or RIGHT number of any descendant item. To get a subtree, select all items with LEFT greater than given LEFT and RIGHT less than given RIGHT number. You get the flat array of items of that tree structure. Next thing is to convert it to tree which means for any given item you need the ability to iterate over all of it's children.

First thing you need to do is to order items by LEFT number, than by RIGHT number.

A small sidenote: we will assume that LEFT and RIGHT numbers are compact so that if your root item has LEFT=1 and RIGHT=10 then for each number X in interval [1, 10] there is item for which X is the value of LEFT or RIGHT. This allows easy calculation of how many descendants particular item has.

So, say we have an flat array and we need to know how many items in array you need to skip to get to given item's next sibling. And that number is (RIGHT-LEFT) (minus one if you do not count the item itself).


# Class that allows performance wise traversing a list of items
# that form a part of nested set structure.
class NestedSetTreePresenter
include Enumerable

# Constructs presenter with a items that form part of nested set,
# offset of first item on desired level and count - number of items
# on current level.
# Items should be ordered by their left bound values.
def initialize(items, offset = 0, count = nil)
@items = items
@offset = offset
@count = count || @items.size
end

# For each item of the same level in nested set as the first item
# calls block passing corresponding item.
def each
i = @offset
bound = @offset + @count
bound = @items.size if bound > @items.size

while i
item = @items[i]
descendants_count = (item.rgt-item.lft)/2
yield item
i += 1 + descendants_count
end
end

# For each item of the same level in nested set as the first item
# calls block passing corresponding item and collection, that
# represent all immediate children of that item. Collection is also
# an instance of this class.
def each_with_children
i = @offset
bound = @offset + @count
bound = @items.size if bound > @items.size

while i
item = @items[i]
descendants_count = (item.rgt-item.lft)/2
yield item, NestedSetTreePresenter.new(@items, i+1, descendants_count)
i += 1 + descendants_count
end
end
end
]]>

I chose not to yield a proxy, container or anything else to minimize the number of objects created.

Here is how to use it:


def print_tree(items, level = 0)
items.each_with_children do |item, children|
puts " "*level + item.name
print_tree(children, level+1)
end
end

print_tree(NestedSetTreePresenter.new(items))

Read: Building tree out of nested set

Topic: Troubleshooting an aegis-permission problem Previous Topic   Next Topic Topic: And Now for Something Completely Different - DIY Bookbinding on the Cheap

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use