What I need to do is create a new object, modify it using a recursive function, then merge it with another object, and do this all in such a way that the values of the new object take precedence over the values in the object I'm merging it with.
Currently, my code works, but I'd like to have more readable code, particularly this statement for the add
operation:
@set.merge!( update(@set, insert(parent, id), @set[parent][1] + 1) )
I've already refactored quite a bit, but I feel like there's a functional way, or at least more readable way, to write what I current have. I want it to be something like: new object → update it → merge it.
Here is the whole class with tests:
# Nested set for comments, for making it easy to load all comments in a list, sorted according to their nesting,
# and for nesting to be indicated.
class Database
def initialize
@set = {}
@largest = -1
end
def fetch
#Need Better syntax for this.
@set.to_a.sort { |el1, el2| el1[1][0] <=> el2[1][0] }
end
def add(parent: nil, id: -1)
if parent
@set.merge!(
update(@set, insert(parent, id), @set[parent][1] + 1)
)
else
@set[id] = [@largest+1, @largest+2]
end
@largest += 2
@set
end
private
def insert(parent_id, id)
parent_range = @set[parent_id]
{
parent_id => [parent_range[0], parent_range[1] + 2],
id => [parent_range[1], parent_range[1] + 1]
}
end
# O(n) * 2^n
def update(old_state, state, target)
# optimization for this:
id,range = old_state.to_a.select{ |entry| entry[1][0] == target || entry[1][1] == target }[0]
# better readability for this:
if range && !state[id]
state[id] =
range.index(target) == 0 ? range.map{|n| n + 2} : [range[0], range[1] + 2]
2.times do |i|
update(old_state, state, range[i] + 1) if range[i] != state[id][i]
end
end
state
end
end
d = Database.new
d.add({id: 1, parent: nil })
d.add({id: 2, parent: nil })
d.add({id: 3, parent: nil })
p d.fetch == [
[1, [0, 1]],
[2, [2,3]],
[3, [4,5]],
]
d.add({id: 4, parent: 1 })
d.add({id: 5, parent: 2 })
d.add({id: 6, parent: 3 })
p d.fetch == [
[1, [0, 3]],
[4, [1, 2]],
[2, [4,7]],
[5, [5,6]],
[3, [8,11]],
[6, [9,10]],
]
d.add({id: 7, parent: 1 })
d.add({id: 8, parent: 7 })
# Final output.
# 1
# 4
# 7
# 8
# 2
# 5
# 3
# 6
p d.fetch == [
[1, [0, 7]],
[4, [1, 2]],
[7, [3, 6]],
[8, [4, 5]],
[2, [8,11]],
[5, [9,10]],
[3, [12,15]],
[6, [13,14]],
]
UPDATE: Will probably just do this:
insert(parent, id)
.yield_self { |obj| update(@set, obj, @set[parent][1] + 1) }
.yield_self { |updated_set| @set.merge!(updated_set) }