Ruby 如何计算迭代器调用yield的次数?
我有一个方法,Ruby 如何计算迭代器调用yield的次数?,ruby,iterator,yield,Ruby,Iterator,Yield,我有一个方法,foo,可以生成对象。我想数一数它产生的物体的数量 我有 def total_foo count = 0 foo { |f| count += 1} count end 但可能有更好的办法。对这位新红宝石手有什么想法吗 以下是foo的定义(它是Rails中的一个助手方法): 假设您只关心foo的副作用,您可以让foo本身计算迭代次数: def foo(resource=@resource) count = 0 resource.thingies.each do
foo
,可以生成对象。我想数一数它产生的物体的数量
我有
def total_foo
count = 0
foo { |f| count += 1}
count
end
但可能有更好的办法。对这位新红宝石手有什么想法吗
以下是foo
的定义(它是Rails中的一个助手方法):
假设您只关心
foo
的副作用,您可以让foo
本身计算迭代次数:
def foo(resource=@resource)
count = 0
resource.thingies.each do |thingy|
bar(thingy) do |b|
count += 1
yield b
end # bar also yields objects
end
count
end
然后:
count = foo { |f| whatever... }
如果选择,也可以忽略返回值,因此只需:
foo { |f| whatever... }
万一你不在乎计数是多少
根据更大的背景,可能有更好的方法来处理所有这些问题。如果您只关心
foo
的副作用,您可以让foo
本身计算迭代次数:
def foo(resource=@resource)
count = 0
resource.thingies.each do |thingy|
bar(thingy) do |b|
count += 1
yield b
end # bar also yields objects
end
count
end
然后:
count = foo { |f| whatever... }
如果选择,也可以忽略返回值,因此只需:
foo { |f| whatever... }
万一你不在乎计数是多少
根据更大的上下文,可能有更好的方法来处理所有这些问题。任何调用
yield
的方法都可以用来构建一个对象,您可以通过该方法在其上调用该对象。请记住,当您调用count
时,迭代器实际上是执行的,因此它应该没有副作用!下面是一个模拟您的场景的可运行示例:
@resources = [[1,2], [3,4]]
def foo(resources = @resources)
resources.each do |thingy|
thingy.each { |b| yield b }
end
end
foo { |i| puts i }
# Output:
# 1
# 2
# 3
# 4
to_enum(:foo).count
# => 4
您可以将参数传递给foo
:
to_enum(:foo, [[5,6]]).count
# => 2
或者,您可以定义foo
来返回枚举数,当它在没有块的情况下被调用时,这就是stdlib迭代器的工作方式:
def foo(resources = @resources)
return to_enum(__method__, resources) unless block_given?
resources.each do |thingy|
thingy.each { |b| yield b }
end
end
foo.count
# => 4
foo([[1,2]]).count
# => 2
foo([[1,2]]) { |i| puts i }
# Output:
# 1
# 2
您可以将一个块传递到到_enum
,当您调用枚举器以返回值时调用该块:
def foo(resources = @resources)
unless block_given?
return to_enum(__method__, resources) do
resources.map(&:size).reduce(:+) # thanks to @Ajedi32
end
end
resources.each do |thingy|
thingy.each { |b| yield b }
end
end
foo.size
# => 4
foo([]).size
# => 0
在这种情况下,使用size
比count
稍微快一点,您的里程数可能会有所不同。任何调用yield
的方法都可以用来构建一个对象,您可以通过该方法在该对象上进行调用。请记住,当您调用count
时,迭代器实际上是执行的,因此它应该没有副作用!下面是一个模拟您的场景的可运行示例:
@resources = [[1,2], [3,4]]
def foo(resources = @resources)
resources.each do |thingy|
thingy.each { |b| yield b }
end
end
foo { |i| puts i }
# Output:
# 1
# 2
# 3
# 4
to_enum(:foo).count
# => 4
您可以将参数传递给foo
:
to_enum(:foo, [[5,6]]).count
# => 2
或者,您可以定义foo
来返回枚举数,当它在没有块的情况下被调用时,这就是stdlib迭代器的工作方式:
def foo(resources = @resources)
return to_enum(__method__, resources) unless block_given?
resources.each do |thingy|
thingy.each { |b| yield b }
end
end
foo.count
# => 4
foo([[1,2]]).count
# => 2
foo([[1,2]]) { |i| puts i }
# Output:
# 1
# 2
您可以将一个块传递到到_enum
,当您调用枚举器以返回值时调用该块:
def foo(resources = @resources)
unless block_given?
return to_enum(__method__, resources) do
resources.map(&:size).reduce(:+) # thanks to @Ajedi32
end
end
resources.each do |thingy|
thingy.each { |b| yield b }
end
end
foo.size
# => 4
foo([]).size
# => 0
在这种情况下,使用size
比count
稍微快一点,您的里程数可能会有所不同。如何定义foo
呢?您现在拥有的东西有什么问题?@akonsu它可以工作,但我想知道是否有更好的Ruby方法。例如,foo.count
@Dennis嗯,我的意思是这是一个清晰易懂的代码。尽管如此,如果您只需要这些对象的计数,为什么要生成所有这些对象呢?但这可能超出了问题的范围。@akonsufoo
也在其他地方被调用,尽管我可以重写它以避免屈服。但是,如果你不能改变方法的行为,这是计算收益率的最佳选择吗?foo
是如何定义的?你现在拥有的有什么问题吗?@akonsu它可以工作,但我想知道是否有更好的Ruby方法来做这件事。例如,foo.count
@Dennis嗯,我的意思是这是一个清晰易懂的代码。尽管如此,如果您只需要这些对象的计数,为什么要生成所有这些对象呢?但这可能超出了问题的范围。@akonsufoo
也在其他地方被调用,尽管我可以重写它以避免屈服。但是,如果你不能改变方法的行为,这是计算收益率的最佳选择吗?这可能有效,但我发现它比我现在拥有的更混乱。虽然我可以重命名foo
,以更清楚地表明它会产生一些结果并返回一个计数。@丹尼斯,我可以理解。正如我提到的,它确实取决于上下文。我展示的内容将您想要的关于foo
的所有内容封装在foo
的定义中。但这可能比其他选择更冗长。根据bar
和thingies
是什么,可能有更好的方法来完成整个过程:这可能行得通,但我发现它比我现在拥有的更混乱。虽然我可以重命名foo
,以更清楚地表明它会产生一些结果并返回一个计数。@丹尼斯,我可以理解。正如我提到的,它确实取决于上下文。我展示的内容将您想要的关于foo
的所有内容封装在foo
的定义中。但这可能比其他选择更冗长。根据bar
和thingies
是什么,可能有更好的方法来完成整个过程:如何将参数传递给foo
?@akonsu只需将附加参数传递给to_enum
方法。文档中说“参数……将在方法中传递给项本身”。这很混乱,是什么项?你知道他们在说什么吗?@akonsu查看Ruby 2.1的文档,应该会更清楚。@AJED32感谢您的编辑,但在看到它之后,我意识到在本例中“大小”块没有真正意义,关键是不要迭代枚举来计算大小。如何将参数传递给foo
?@akonsu只需将附加参数传递给to_enum
方法。文档中说“参数……将在方法中传递给项本身。”这让人困惑,什么项?你知道他们在说什么吗?@akonsu查看Ruby 2.1的文档,应该会更清楚。@AJED32感谢您的编辑,但在看到它之后,我意识到在这种情况下,“大小”块没有真正意义,关键是不要迭代枚举来计算大小。