著作一覧 |
ちょっとおもしろかったのでメモ。
なんらかの方法で作ったコレクションの各要素に対して処理を実行するのだが、うまくいかない要素もある。そういう要素を別のコレクションに入れておいて、後から別の方法で処理する。この処理は最初の処理と違って処理のためのリソースの取得に無闇と時間がかかる。しかもリソースが利用できるものかどうかは、実際に処理してみないとわからない。その判断にもえらく時間がかかる。そこで、1つ前の要素と同じリソースが利用できるときにはそれを利用するようにしてちょっとした高速化を考える。しかし遅い。
2nd_collection = [] org_collection.each do |e| unless proc(e) 2nd_collection << e end end prior_resource = nil prior_elem = nil 2nd_collection.each do |e| if e.same_type(prior_elem) unless proc2(e, prior_resource) error_proc(e) end else prior_elem = e resource = search_resource(e) next unless resource unless proc2(e, resource) error_proc(e) else prior_resource = resource end end end
あ、Rubyで書いたらすぐバグがわかる(そこまでひどくないのでちょっと直した)。が、それは良いとして、遅いのは当然で、最初の処理用の並び順は、次の処理の並び順にとってはでたらめも良いところだからだ。
そこで次のように直した。
2nd_collection.sort do |x, y| # for 2nd loop end.each do |e|
すると猛烈な速度で終わるようになった。しかし、処理結果はえらくでたらめなものとなりましたとさ。
というバグの発現の仕方がおもしろかったのだった。
ジェズイットを見習え |
「必要なリソースの種類」というものが取り出せるのであれば、先に分類するほうがわかりやすいのでは。<br><br>2nd_collection.group_by {|e|e.resource_type}.each do |type, elems|<br> if resource = search_resource(e)<br> elems.each do |e|<br> proc2(e, prior_resource) or error_proc(e)<br> end<br> end<br>end
あ、コピペミス
なるほど、group_byってこういう用途には便利ですね。<br>ふーむ。