在 Ruby 中对树状结构(tree)进行 map 操作

class BookChapter < ActiveRecord::Base
belongs_to :parent, :class_name => 'BookChapter', :foreign_key => 'parent_id'

has_many :children,
:class_name => 'BookChapter',
:foreign_key => 'parent_id',
:order => 'play_order'

def map(parent_mapping=nil, &block)
result = block.call self, parent_mapping
children.each do |chapter|
chapter.map result, &block
end
result
end

end


[b]usage: [/b]


class EpubChapter
attr_accessor :title
def initialize
@children = []
end

def add_child(child)
@children << child
end
end

book_chapter = BookChapter.first
book_chapter.map do |chapter, parent|
# 这里处理父子关系,例如:
child = EpubChapter.new
child.title = chapter.title
parent.add_child child if parent
child
end


这是改进过之后的版本了,之前一个版本使用简单些,但是有接口上的双向依赖,就不贴出来了。

然后呢,还可以把这个方法抽出来,放到 module 中,这样就可以到处使用了:
module MappableTree
def map(parent_mapping=nil, &block)
result = block.call self, parent_mapping
children.each do |child|
child.map result, &block
end
result
end
end

class Nokogiri::XML::Node
include MappableTree
end


还有点味道,这个 map 方法要求实现类必须有一个 children 方法,而且这个 children 方法的返回值还必须有一个 each 方法,稍微封装一下,变成:
module MappableTree
def map(parent_mapping=nil, &block)
result = block.call self, parent_mapping
each_child do |child|
child.map result, &block
end
result
end
end

class Nokogiri::XML::Node
include MappableTree
def each_child &block
children.each &block
end
end

这样耦合就不那么紧了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值