Ruby 拆分数组两个与分区和with_index



你能解释一下这个结构的Ruby行为的逻辑或算法吗?

arr = [1,2,3,4,5]
arr.partition.with_index{|_,index| index>2} 

如何形式化逻辑时遍历枚举给出 2 个数组输出。 当我们只称单个partition它很清楚 - 只是方法行为时,但是当它落后于with_index这种结构对我来说变得"神奇"时。

谢谢

UPD:条件不在partition块中,而是在单独的"可枚举"对象方法块中。此方法with_index这第二层互动对我来说很有趣。为什么with_index条件对分割结果有影响?这是从partition文档中不清楚的行为。

你可能已经在 Ruby 文档中读过partition

如果未给出块,则返回枚举器。

> arr = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
> arr.partition
=> #<Enumerator: ...>

您将在Enumerable中许多方法的说明中看到相同的内容,但返回的枚举器没有太多详细信息。

枚举器链接的关键在于返回Enumeratoreach方法的行为。例如,partition返回的Enumerator具有行为类似于partitioneach方法。这就是您如何能够通过单个块并获得partitionwith_index的组合行为。如果您通过几个步骤执行此操作,它可能会有所帮助:

> enumerator = arr.partition
=> #<Enumerator: ...>
> enumerator.each { |n| n < 3 } # just to demonstrate `each` performing a partition
=> [[1, 2], [3, 4, 5]]
> enumerator.with_index { |_, index| index > 2 }
=> [[4, 5], [1, 2, 3]]

另一种思考方式是,没有给出块的partition就像将:partition传递给enum_for

例如
> another_enum = arr.enum_for(:partition)
=> #<Enumerator: ...>
> another_enum.with_index { |_, index| index > 2 } # same result as above
=> [[4, 5], [1, 2, 3]]

当索引> 2 ruby 创建一个包含其余值的新数组

分区

返回两个数组,第一个数组包含块计算结果为 true 的枚举元素,第二个数组包含其余数组。 如果未给出块,则返回枚举器。

arr = [1,2,3,4,5]
arr.partition.with_index{|_,index| index>2} 
=> [[4, 5], [1, 2, 3]]

第一个数组将包含[4,5],因为它满足条件index > 2

第二个数组将包含所有其他元素:[1,2,3]

您正在将枚举模块和枚举器类混为一谈。模块 Enumerable 中的所有方法都是实例方法,要求其接收器是枚举器(类枚举器的实例)。

在自定义类中使用"include Enumerable",并实现返回枚举器的 each 方法:

def each
return enum_for(:each) unless block_given?
@apples.each { |apple| yield apple }
end

当在包含 Enumerable 的类的实例上执行 Enumerable 中包含的方法时,Ruby 会在实例和 Enumerable 方法之间隐式插入该方法。

with_index不是可枚举模块的方法。它是枚举器类的实例方法。现在请记住,我说过,当您在自定义类中包含 Enumerable 模块并实现 each 方法时,每个方法都可用于返回枚举器实例。因此,具有每个方法返回枚举器的类可以通过(显式)在类的实例和with_index之间插入每个方法来使用方法 Enumerator#with_index。或者它可以在可枚举模块方法上调用with_index,因为它返回一个枚举器实例:

arr = [1,2,3,4,5]
arr.partition.with_index{|_,index| index>2} 

在上面的示例中,分区是枚举模块的实例方法,with_index是枚举器类的实例方法。 分区返回一个可以采用with_index的枚举器实例。

现在要了解此语句的作用,您只需查看解释分区作用的枚举文档:

返回两个数组,第一个数组包含块计算结果为 true 的枚举元素,第二个数组包含其余数组。

因此,在您的情况下,它是确定索引是否大于 2。如果是,则将其放入一个数组中,否则放入另一个数组中。