至少在Ruby 1.9.3中,Enumerable
个对象没有length
属性。
据我所知,任何Enumerable
都是一个集合,sort
和find_index
等方法证明了这一点。
一个集总是有一个明确定义的长度(......对吗?),那为什么这不是一个属性?
答案 0 :(得分:10)
Enumerable有count
方法,通常是枚举的直观“长度”。
但为什么不把它称为“长度”?好吧,因为它的运作方式非常不同。在Ruby的内置数据结构中,如Array
和Hash
,length
只是检索数据结构的预先计算的大小。它应该总是立即返回。
然而,对于Enumerable#count
,它无法知道它正在运行什么类型的结构,因此没有快速,巧妙的方法来获得枚举的大小(这是因为Enumerable
是一个模块,可以包含在任何类中)。获取枚举大小的唯一方法是实际枚举它并按计算进行计数。对于无限枚举,count
将(适当地)循环永远,永不返回。
答案 1 :(得分:2)
不能保证Enumerables有长度 - 对于Enumerable混入的对象的唯一要求是它响应#each
,这会导致它返回系列中的下一个项目,{{1}这允许比较可枚举的值。像#<=>
这样的方法将在排序过程中枚举整个集合,但可能不会提前知道集合的边界。考虑:
#sort
这个枚举将被调用,直到迭代器生成值&#34; 500&#34;,这将导致它停止枚举。收集并排序结果集。但是,class RandomSizeEnumerable
include Enumerable
def each
value = rand 1000
while value != 500
yield value
value = rand 1000
end
end
# Not needed for this example, but included as a part of the Enumerable "interface".
# You only need this method if #max, #min, or #sort are used on this class.
def <=>(a, b)
a <=> b
end
end
方法在此上下文中没有意义,因为在迭代器耗尽之前,长度是不可知的!
我们可以就#length
之类的结果调用#length
,因为它们会返回一个数组:
#sort
传统上,当长度已知并且可以在恒定时间内返回时使用p RandomSizeEnumerable.new.sort.length # 321
p RandomSizeEnumerable.new.sort.length # 227
p RandomSizeEnumerable.new.sort.length # 299
,而当长度可能不是时,往往会使用#length
(有时#count
)提前知道并且需要通过迭代结果集来计算(因此,采用线性时间)。如果您需要Enumerable提供的结果集的大小,请尝试使用 #size
.to_a.length
。
答案 2 :(得分:0)
Enumerable
实际上不是一个类,它是一个模块 - 多个类使用的交叉功能的集合。
例如,Array
,Set
和Hash
所有include
- 您可以调用它们上的任何Enumerable
方法。
Enumerable
值得注意的是,它只需要很少的“主机”类。您需要做的就是定义each
方法和include Enumerable
,您可以免费获得所有这些方法!例如:
class CountUntil
def initialize(number)
@number = number
end
include Enumerable
def each
current = 0
while current < @number
yield current
current += 1
end
end
end
# Usage:
CountUntil.new(10).map { |n| n * 5 }
# => [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
正如您所看到的,我从未定义过CountUntil#map
,但我免费提供Enumerable
。
要解决有关length
的问题:并非所有包含Enumerable
的类都定义了长度,即使大多数类都有。例如,Enumerator
可用于创建无限流。