[1,2,3].partition.inject(0) do |acc, x|
x>2 # this line is intended to be used by `partition`
acc+=x # this line is intended to be used by `inject`
end
我知道我可以使用不同的方法来写上面的节,但这在这里并不重要。
我想问的是为什么有人要在“链”的开头使用partition
(或其他方法,如keep_if
、delete_if
)?
在我的示例中,在链接 inject
之后,我无法使用 partition
。我可以使用 each
编写上面的节:
[1,2,3].each.inject(0) do |acc, x|
x>2 # this line is intended to be used by `partition`
acc+=x # this line is intended to be used by `inject`
end
它会是一样的,对吧?
我知道 x>2
将被 partition
丢弃(而不是使用)。只有 acc+=x
可以完成这项工作(在这种情况下对所有元素求和)。
我这样写只是为了表明我的“意图”:我想像这样在链中使用 partition
[].partition.inject(0)
.
我知道上面的代码不会像我预期的那样工作,而且我知道我可以在 block 之后链接(}.map
,如 Neil Slater 所提到的)。
我想知道为什么以及何时 partition
(以及其他方法,如 keep_if
、delete_if
等)变为 each
(在上述情况下,只返回数组的元素,就像 partition
所做的那样)。
在我的示例中,partition.inject
,partition
变成了 each
因为 partition
不能接受条件 (x> 2
).
但是 partition.with_index
(正如 Boris Stitnicky 所提到的)有效(我可以对数组进行分区并为我想要的任何东西使用索引):
shuffled_array
.partition
.with_index { |element, index|
element > index
}
附言。这不是关于如何获取大于 2 的元素之和的问题。
最佳答案
这是一个有趣的情况。查看您的代码示例,您显然是 Ruby 的新手,也许还不熟悉编程。然而,您设法提出了一个非常困难的问题,该问题基本上与 Enumerator
类有关,它是公众了解最少的类之一,特别是自从引入 Enumerator::Lazy
以来。对我来说,你的问题很难,我无法提供全面的答案。然而,关于您的代码的评论不适合 OP 下的评论。这就是我添加此非答案的原因。
首先,让我们注意到您的代码中有一些糟糕的地方:
无用行。在这两个 block 中,x>2
行无用,因为它的返回值被丢弃。
[1,2,3].partition.inject(0) do |x, acc|
x>2 # <---- return value of this line is never used
acc+=x
end
[1,2,3].each.inject(0) do |x, acc|
x>2 # <---- return value of this line is never used
acc+=x
end
在进一步讨论您的代码示例时,我将忽略这一无用的行。
无用的#each
方法。写起来没用
[1,2,3].each.inject(0) do |x, acc|
acc+=x
end
这就够了:
[1,2,3].inject(0) do |x, acc|
acc+=x
end
无用的 #partition
方法。 而不是:
[1,2,3].partition.inject(0) do |x, acc|
acc+=x
end
你可以这样写:
[1,2,3].inject(0) do |x, acc|
acc+=x
end
或者,正如我所写的那样:
[ 1, 2, 3 ].inject :+
但是,您问了一个关于在枚举器模式下使用 #partition
方法的深层次问题。在讨论了您的代码的琐碎的新手问题之后,我们剩下的问题是应该如何使用 #partition
、#keep_if
等的枚举器返回版本,或者更确切地说,使用它们的有趣方式是什么,因为每个人都知道我们可以将它们用于链接:
array = [ *1..6 ]
shuffled_arrray = array.shuffle # randomly shuffles the array elements
shuffled_array
.partition # partition enumerator comes into play
.with_index { |element, index| # method Enumerator#with_index comes into play
element > index # and partitions elements into those greater
} # than their index, and those smaller
还有这样的:
e = partition_enumerator_of_array = array.partition
# And then, we can partition the array in many ways:
e.each &:even? # partitions into odd / even numbers
e.each { rand() > 0.5 } # partitions the array randomly
# etc.
一个容易理解的优点是,不用写得更长:
array.partition &:even?
你可以写得更短:
e.each &:even?
但我基本上可以肯定,枚举器为程序员提供的功能不仅仅是链接集合方法和稍微缩短代码。因为不同的普查员做的事情非常不同。有些,例如 #map!
或 #reject!
,甚至可以修改它们操作的集合。在这种情况下,可以想象可以将不同的枚举器与同一个 block 组合起来做不同的事情。这种不仅可以改变 block ,还可以改变传递给它们的枚举器的能力提供了组合能力,这很可能用于使一些原本冗长的代码变得非常简洁。但我无法提供一个非常有用的具体示例。
总而言之,Enumerator
类在这里主要是为了链接,而要使用链接,程序员并不需要对Enumerator
进行详细的理解。但我怀疑关于使用 Enumerator
的正确习惯可能与例如参数化子类化的正确习惯一样难以学习。我怀疑我还没有掌握使用枚举器的最强大方法。
关于ruby - 链接分区,keep_if 等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21936171/