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

これらすべての配列トラバーサルを防ぐには、ハッシュを使用する方が良い方法です。2 番目のハッシュを使用して、孤児をログに記録して検索する私のソリューションは次のとおりです。

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 に答える
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 に答える