我有一组对象,比如" people",彼此之间有关系。我希望能够从一个人到另一个人,这将是阵列中的另一个对象。
所以我想出了这个:
class Person
attr_accessor :name, :parent, :collection
def parents
rtn = []
pid = @parent
while pid
p = collection.select{|i|i.name == pid}.first
if p
rtn << p
pid = p.parent
else
pid = nil
end
end
rtn
end
def to_s;@name;end
end
class PersonCollection < Array
def <<(obj)
obj.collection = self
super
end
end
...允许我这样做:
p1 = Person.new
p1.name = 'Anna'
p2 = Person.new
p2.name = 'Bob'
p2.parent = 'Anna'
pc = PersonCollection.new
pc << p1
pc << p2
pp p2.parents
请原谅我相当笨重的例子。关键目标是让集合成员能够访问同一集合的其他成员。还有更好的方法吗?
答案 0 :(得分:1)
有更好的方法吗?
是。使对象保持对其相关对象的引用:
class Person
attr_accessor :name, :parent, :collection
def parents
if parent
[parent].concat(parent.parents)
else
[]
end
end
def to_s
name
end
end
p1 = Person.new
p1.name = 'Anna'
p2 = Person.new
p2.name = 'Bob'
p2.parent = p1
p2.parents
现在返回[p1]
,没有数组遍历,字符串比较或PersonCollection
。
答案 1 :(得分:1)
使用哈希将是更好的方法,以防止所有这些数组遍历。这是我的解决方案,使用第二个哈希来记录和查找 孤儿 :
class Person
attr_accessor :name, :parent, :parent_key, :collection
def parents
if parent
[parent].concat(parent.parents)
else
[]
end
end
def children
self.collection.values.select{ |person| person.parent === self }
end
def descendants
self.collection.values.select{ |person| person.parents.include? self }
end
def to_s
self.name
end
end
class PersonCollection < Hash
attr_accessor :orphans
def initialize
self.orphans = Hash.new
super
end
def store (key,obj)
obj.collection = self
if !obj.parent_key.nil?
if self[obj.parent_key]
#this person's parent is already in the Hash
obj.parent = self[obj.parent_key]
else
#this person's parent is missing, so add this person to the orphans hash
self.orphans[obj.parent_key] ||= []
self.orphans[obj.parent_key] << obj
end
end
if orphans[obj.name]
# this person has an array of orphans, so lets finally set their parents
self.orphans[obj.name].each do |orphan|
orphan.parent = obj
end
# finally, clean up the hash after taking care of theses orphans
self.orphans.delete(obj.name)
end
super
end
end
总结我的方法:
self.orphans
中。< / LI>