知道其集合/数组的ruby对象

时间:2012-12-06 03:07:50

标签: ruby algorithm oop design-patterns

我有一组对象,比如" 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   

请原谅我相当笨重的例子。关键目标是让集合成员能够访问同一集合的其他成员。还有更好的方法吗?

2 个答案:

答案 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

总结我的方法:

  1. 如果某人在添加到收藏夹中时可以找到他/她的父母。宾果。
  2. 如果某人无法找到他/她的父母,则在添加到该集合时,他/她的对象会以他/她父母的名字记录/存储在哈希self.orphans中。< / LI>
  3. 如果一个人在他/她的名字下有孤儿被添加到集合中,那些孤儿会被更新,所以他们最终知道他们的父母。