1

再帰を使用せずにRuby on Railsのacts_as_nested_setの任意のノードからJSONハッシュを返す高速でクリーンな方法はありますか?

参照用の再帰的ソリューションは次のとおりです。

class Node < ActiveRecord::Base
  has_many :products
  def json_hash
    if children.size > 0
      children.collect { |node| { node.name => node.json_hash }.to_json
    else
      { node.name => node.products.find(:all).collect(&:name) }.to_json
    end
  end
end
4

2 に答える 2

2

使用している再帰的なソリューションに代わるさまざまな方法を示すツリー トラバーサルに関するウィキペディアの記事があります。特定のケースでそれらを使用するのは難しいかもしれませんが、可能でなければなりません。

ただし、私の質問は、再帰の代わりに反復を使用したい特定の理由はありますか? 反復的な解決策のいずれも、ほぼクリーンになるとは思いません。ツリーが大きすぎて、スタック スペースが不足していませんか (かなり大きくなければなりません)。そうでなければ、反復ソリューションが本当に高速になるかどうかはわかりません。

ただし、パフォーマンスの問題が発生している場合は、改善の可能性が1つあります...しかし、レールを知らないので、それが正確かどうかはわかりません:

find メソッドは新しい配列を返しますか? もしそうなら、あなたはおそらく .collect! を呼び出したいと思うでしょう! .collect の代わりに、find が配列を作成する場合、単に配列を作成し、それを collect の呼び出し (配列も作成する) に捨てるだけなので、これは非常に効率的ではなく、速度が低下する可能性があります。そこに大きな木があればたくさん。

そう

{ node.name => node.products.find(:all).collect(&:name) }.to_json

になるかもしれません

{ node.name => node.products.find(:all).collect!(&:name) }.to_json

EDIT:また、ハッシュのハッシュを作成してから、すべてを一気にjsonに変換する方が、あなたがやっているように断片的に変換するよりも効率的かもしれません。

そう

class Node < ActiveRecord::Base
  has_many :products
  def json_hash
    if children.size > 0
      children.collect { |node| { node.name => node.json_hash }.to_json
    else
      { node.name => node.products.find(:all).collect!(&:name) }.to_json
    end
  end
end

になるかもしれません

class Node < ActiveRecord::Base
  has_many :products
  def json_hash
    to_hash.to_json
  end

  def to_hash
    if children.size > 0
      children.collect { |node| { node.name => node.to_hash }
    else
      { node.name => node.products.find(:all).collect!(&:name) }
    end
  end
end

これが機能し、より効率的であるかどうかは、演習として残します;-)

于 2008-09-03T07:24:35.383 に答える
1

JSONifier!

node.to_json(:include=>{:products=>{:include=>:product_parts}})
于 2010-08-27T20:26:13.187 に答える