为什么我们必须在枚举器对象上调用to_a?

Don*_*ato 3 ruby

链接each_sliceto_a混淆我.我知道它each_slice是Enumerable的成员,因此可以在数组之类的可枚举对象上调用,并chars返回一个字符数组.

我也知道each_slice将数组分成n个元素,在下面的例子中为2.如果没有给出块each_slice,则它返回一个Enumerator对象.

'186A08'.chars.each_slice(2).to_a
Run Code Online (Sandbox Code Playgroud)

但是,to_a如果each_slice已经将数组分组为n个元素,为什么我们必须调用枚举器对象?为什么ruby只评估枚举器对象是什么(这是n个元素的集合)?

Nat*_*ate 6

枚举器的目的是懒惰的评估.当你调用each_slice时,你会得到一个枚举器对象.此对象不预先计算整个分组数组.相反,它会根据需要计算每个"切片".这有助于节省内存,并且还允许您在代码中具有相当大的灵活性.

这个堆栈溢出帖子中有很多信息,你会觉得它很有用:

Ruby中Enumerator类的目的是什么?

为了给你一个简单而干燥的回答你的问题"为什么我必须打电话给_a ......"答案是,它没有.它还没有在阵列中循环.到目前为止,它只是定义了一个对象,它说当它通过数组时,你一次只想要两个元素.然后,您可以自由地强制它对可枚举中的所有元素进行计算(通过调用to_a),或者您也可以使用nexteach经过然后中途停止(可能只计算其中一半而不是计算所有这些并将下半场扔掉了).

它类似于Range类如何不构建范围中的元素列表.(1..100000)不会生成100000个数字的数组,而是定义一个具有最小值和最大值的对象,并且可以对其执行某些操作.例如(1..100000).cover?(5)没有构建一个庞大的数组来查看该数字是否在那里,而是只看到5是否大于或等于1且小于或等于100000 .

这一切的目的是性能和灵活性.

可能值得考虑您的实现是否实际需要预先建立一个数组,或者是否可以通过迭代枚举器来实际保持RAM消耗.(如果您的真实世界场景如您所描述的那样简单,那么枚举器将无济于事,但如果阵列实际上很大,则枚举器可以帮助您很多).