Ruby 使用分区和 with_index 将数组拆分为两个
Ruby Split array for two with partition and with_index
你能解释一下这个结构的ruby行为的逻辑或算法吗:
arr = [1,2,3,4,5]
arr.partition.with_index{|_,index| index>2}
如何在遍历 Enumerable 时将逻辑形式化,给出 2 个数组输出。
当我们只调用 single partition
时,它的清晰 - 只是方法行为,但是当它落后于 with_index
时,这个结构对我来说变成了 "Magical" 。
谢谢
UPD:条件不在 partition
块中,它在单独的 'Enumerable' 对象方法块中。这个方法是with_index
。 第二层的互动对我来说很有趣。为什么with_index
的条件会影响分区结果? 这种行为在 partition
文档中并不清楚。
当索引 > 2 ruby 使用其余值创建一个新数组
分区
Returns two arrays, the first containing the elements of enum for which the block evaluates to true, the second containing the rest.
If no block is given, an enumerator is returned instead.
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]
您可能已经在 Ruby 文档中阅读了 partition
:
If no block is given, an enumerator is returned instead.
> arr = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
> arr.partition
=> #<Enumerator: ...>
您会在 Enumerable
中的许多方法的描述中看到相同的内容,但没有太多关于返回的枚举器的详细信息。
枚举器链接的关键在于返回的 Enumerator
中 each
方法的行为。例如,partition
返回的 Enumerator
有一个 each
方法,其行为类似于 partition
。这就是您能够传递单个块并获得 partition
和 with_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]]
您正在混淆 Enumerable 模块和 Enumerator class。 Enumerable 模块中的所有方法都是实例方法,要求它们的接收者是枚举器(class 枚举器的实例)。
您在自定义 class 中使用了 "include Enumerable" 并实现了一个 return 枚举器的 each 方法:
def each
return enum_for(:each) unless block_given?
@apples.each { |apple| yield apple }
end
当在包含 Enumerable 的 class 实例上执行 Enumerable 中包含的方法时,Ruby 会在实例和 Enumerable 方法之间隐含地插入方法。
with_index 不是 Enumerable 模块的方法。它是 Enumerator class 的一个实例方法。现在请记住我曾说过,当您在自定义 class 中包含 Enumerable 模块并实现 each 方法时,每个方法都可以用于 return 枚举器实例。因此,classes 有一个方法,每个 returns 枚举器可以通过(明确地)在 [=35= 的实例之间插入每个方法来使用方法 Enumerator#with_index ] 和 with_index。或者它可以在可枚举模块方法上调用 with_index,因为 return 是一个枚举器实例:
arr = [1,2,3,4,5]
arr.partition.with_index{|_,index| index>2}
上例中partition是Enumerable模块的实例方法,with_index是Enumeratorclass的实例方法。 partition return 是一个枚举器实例,可以使用 with_index。
现在为了理解这条语句的作用,您可以简单地查看 Enumerable 文档,它解释了分区的作用:
Returns 两个数组,第一个包含块评估为 true 的枚举元素,第二个包含其余元素。
因此在您的情况下,它正在确定索引是否大于 2。如果是,则将其放入一个数组中,否则放入另一个数组中。
你能解释一下这个结构的ruby行为的逻辑或算法吗:
arr = [1,2,3,4,5]
arr.partition.with_index{|_,index| index>2}
如何在遍历 Enumerable 时将逻辑形式化,给出 2 个数组输出。
当我们只调用 single partition
时,它的清晰 - 只是方法行为,但是当它落后于 with_index
时,这个结构对我来说变成了 "Magical" 。
谢谢
UPD:条件不在 partition
块中,它在单独的 'Enumerable' 对象方法块中。这个方法是with_index
。 第二层的互动对我来说很有趣。为什么with_index
的条件会影响分区结果? 这种行为在 partition
文档中并不清楚。
当索引 > 2 ruby 使用其余值创建一个新数组
分区
Returns two arrays, the first containing the elements of enum for which the block evaluates to true, the second containing the rest. If no block is given, an enumerator is returned instead.
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]
您可能已经在 Ruby 文档中阅读了 partition
:
If no block is given, an enumerator is returned instead.
> arr = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
> arr.partition
=> #<Enumerator: ...>
您会在 Enumerable
中的许多方法的描述中看到相同的内容,但没有太多关于返回的枚举器的详细信息。
枚举器链接的关键在于返回的 Enumerator
中 each
方法的行为。例如,partition
返回的 Enumerator
有一个 each
方法,其行为类似于 partition
。这就是您能够传递单个块并获得 partition
和 with_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]]
您正在混淆 Enumerable 模块和 Enumerator class。 Enumerable 模块中的所有方法都是实例方法,要求它们的接收者是枚举器(class 枚举器的实例)。
您在自定义 class 中使用了 "include Enumerable" 并实现了一个 return 枚举器的 each 方法:
def each
return enum_for(:each) unless block_given?
@apples.each { |apple| yield apple }
end
当在包含 Enumerable 的 class 实例上执行 Enumerable 中包含的方法时,Ruby 会在实例和 Enumerable 方法之间隐含地插入方法。
with_index 不是 Enumerable 模块的方法。它是 Enumerator class 的一个实例方法。现在请记住我曾说过,当您在自定义 class 中包含 Enumerable 模块并实现 each 方法时,每个方法都可以用于 return 枚举器实例。因此,classes 有一个方法,每个 returns 枚举器可以通过(明确地)在 [=35= 的实例之间插入每个方法来使用方法 Enumerator#with_index ] 和 with_index。或者它可以在可枚举模块方法上调用 with_index,因为 return 是一个枚举器实例:
arr = [1,2,3,4,5]
arr.partition.with_index{|_,index| index>2}
上例中partition是Enumerable模块的实例方法,with_index是Enumeratorclass的实例方法。 partition return 是一个枚举器实例,可以使用 with_index。
现在为了理解这条语句的作用,您可以简单地查看 Enumerable 文档,它解释了分区的作用:
Returns 两个数组,第一个包含块评估为 true 的枚举元素,第二个包含其余元素。
因此在您的情况下,它正在确定索引是否大于 2。如果是,则将其放入一个数组中,否则放入另一个数组中。