【发布时间】:2013-09-09 21:16:15
【问题描述】:
在 ruby 中编写带有突变的迭代代码时,我经常发现自己遵循以下模式:
def build_x some_data
x = [] # or x = {}
some_data.each do |data|
x.some_in_place_update! (... data ...)
end
x
end
(x 通常与some_data 的形状不同,所以简单的map 是不行的。)
有没有更惯用或更好的方法来编写遵循这种模式的代码?
[编辑] 一个真实的例子:
def to_hierarchy stuff
h = {}
stuff.each do |thing|
path = thing.uri.split("/").drop(4)
sub_h = h
path.each do |segment|
sub_h[segment] ||= {}
sub_h = sub_h[segment]
end
sub_h.merge!(
data: thing.data,
)
end
h
end
这从things 的平面列表开始,它们具有相关但不同的uris。它将这个平面列表转换为层次结构,将共享相同segments 的things 与uri 分组。这遵循我描述的模式:初始化h,循环一些数据并沿途改变h,然后在最后吐出h。
[edit2]另一个相关的例子
def count_data obj
i = if obj[:data] then 1 else 0
obj.each do |k, v|
i += count_statements v unless :data == k
end
i
end
【问题讨论】:
-
不清楚你想要什么。
x = []后跟x.some_in_place_update!(data)使some_in_place_update!成为Array的方法,它的名字暗示它正在就地修改数组x(给定some_data的元素作为输入)即使它是空的。你有没有真的用新方法修补Array?了解some_in_place_update!正在做的事情会很有帮助。 -
你能举出一两个具有这种模式的实际方法的例子吗?
-
@Borodin“就地更新”可能是描述我真正意思的不好方式。我试图传达这样一个想法,即对象
x正在被该方法调用改变。 -
@DanBurton:啊!你想要
each_with_object。我会写一个答案。
标签: ruby design-patterns idioms mutation