0

我有一组相互关联的对象,比如“人”。我希望能够从一个人到另一个人,这将是数组中的另一个对象。

所以我想出了这个:

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   

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

4

2 回答 2

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.

于 2012-12-06T03:53:02.363 回答
1

使用Hash将是一种更好的方法,可以防止所有这些数组遍历。这是我使用第二个哈希记录和查找您的孤儿的解决方案:

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,他/她的对象将被记录/存储在他/她的父母姓名下的哈希中。
  3. 如果一个人在添加到集合时以他/她的名义有孤儿,则这些孤儿会更新,以便他们最终知道他们的父母。
于 2012-12-09T08:47:40.790 回答