25

使用 Ruby,我想评估数组中的所有项目,如果它们都通过条件测试,则返回 true。

我可以使用例如array.all? { |value| value == 2 }

所以:

> array=[2,2]
> array.all? { |value| value == 2 }
=> true
> array=[2,3]
> array.all? { |value| value == 2 }
=> false

伟大的!

但是,为什么一个空数组能通过这个测试呢?

> array=[]
> array.all? { |value| value == 2 }
=> true

这不应该返回false吗?

如果我需要它返回false,我应该如何修改方法?

4

10 回答 10

29

这是一个空洞的真理。这是一个普遍量化的标准解释,即

collection.all? { |x| some_predicate(x) }

在一个空的collection,但众所周知,当人们第一次在正式场合看到它时,会觉得它违反直觉。思考为什么这是首选语义的一种好方法是考虑如何实现all?.

要使您的测试要求数组非空,只需执行

array.any? && array.all? { |x| x == 2 }

请注意,array.any?无论阵列有多大,它都很快,而array.all? { |x| x == 2 }可能很慢,具体取决于阵列的大小array和稀有2程度。所以放第array.any?一个。

另请注意,在某些退化的情况下这不起作用,例如 if arrayis[nil][false]. 如果可能出现这样的情况,请替换array.any?array.any? { true }.

于 2013-05-21T05:49:56.247 回答
10

在 Ruby 中,您永远不能遍历空集合(数组、哈希等),因此在您的情况下,您的块永远不会被执行。如果块永远不会被执行,all?则返回 true(没有条件使结果为 false)。

阅读Ruby文档all?

您可以通过以下方式简单地实现您的目标

  !array.empty? && array.all? { |value| value == 2 }
于 2013-05-21T06:32:01.240 回答
5

文档说:“如果块从不返回 false 或 nil,则该方法返回 true。 ” 在空数组的情况下,块永远不会执行,因此该方法将始终返回true。就返回false而言,您将不得不arr.empty?

于 2013-05-21T05:42:20.583 回答
4

该数组中没有未通过测试的项目。我认为您可能需要对数组长度进行测试。

于 2013-05-21T05:29:34.223 回答
1

去吧

!(array.empty? || array.any? {|x| x != 2})

(这具有快速失败的额外优势——也就是说,可以正确评估它而无需扫描整个阵列。)

于 2013-05-21T05:34:39.420 回答
0

由于数组中没有测试失败的项目,因此它返回 true。所以只需使用类似的东西:

array.size > 0 and array.all? { |value| value == 2}

或类似的东西。

于 2013-05-21T05:36:08.193 回答
0

零、空集合、空矩阵等总是有点特殊,如果不是完全有问题的话。希腊人很清楚他们为什么不在自然整数中计算 0。

Methodall?会第一个问“你为什么在一个空数组上打电话给我?” 当那里什么都没有时,您所说的“全部”是什么意思?这是一个矛盾。该方法进行了简短的思考,并回答true了其他三个答案中概述的原因。请记住,您一开始就谈论空数组的“所有元素”是错误的。

于 2013-05-21T05:41:13.947 回答
0

正如 Amit Kumar Gupta 所写,它是普遍量化的标准解释。我不知道你为什么期望它是false。在这里,你可以看到它应该是true通过推断的。


全称量词等价于连词,因此(“<=>”表示等价):

"for all x in [a, b, c], P(x)" <=> "P(a) and P(b) and P(c)"

请注意,任何命题都等价于 true 和自身的合取,因此:

"for all x in [a, b, c], P(x)" <=> "true and P(a) and P(b) and P(c)"

如果你将集合中的元素减少到两个,你会得到:

"for all x in [a, b], P(x)" <=> "true and P(a) and P(b)"

再到一个元素:

"for all x in [a], P(x)" <=> "true and P(a)"

现在,空集会发生什么?自然,

"for all x in [], P(x)" <=> "true"


通过注意到存在量化等同于析取,您还可以看到您应该期望false在空集上使用存在量化。

于 2013-05-21T05:53:41.580 回答
0

一切的源头?方法说它使用静态变量(最初设置为true),然后在静态变量值和迭代结果之间进行AND运算,最终返回这个静态变量作为结果。

因为数组是空的,所以红宝石永远不会在这个空数组上迭代,结果呢?方法将返回设置为 true 的静态变量。

于 2015-04-17T19:50:32.917 回答
0

首先确保数组不为空。然后:

array.compact.present? && array.all? {|x| x != 2}
于 2015-05-29T03:47:23.157 回答