如何使用any、all和none简化循环(附代码)

93 阅读2分钟

Ruby有一些有用的枚举方法(数组、哈希等),这篇文章将讨论any?,all?, 和none?

对于这篇文章中使用的例子,一个订单模型可能有许多支付模型(客户可以使用分割支付来支付订单)。

为了检查一个订单是否有任何已付款项,一个基于循环的实现可能看起来像这样:

has_paid_payment = false

order.payments.each do |payment|
  if payment.status == "paid"
    # one of the payment is paid
    has_paid_payment = true
    break
  end
end

if has_paid_payment
  # ...
end

我们可以用**any?**来简化上面的代码,就像这样:

if order.payments.any?{ |payment| payment.status == 'paid'}
  # this will be executed if there is at least one paid payment
end

方法可以接收一个块,如果该块返回的值不是错误或零,它将返回真。(即:真,或123,或 "abc")

如果没有提供块,它将对元素进行自我检查:

order.payments.any?

# is equivalent to
order.payments.any? { |payment| payment }

要检查一个订单的所有款项是否已经支付,一个基于循环的实现可能看起来像这样:

fully_paid = true

order.payments.each do |payment|
  if payment.status != "paid"
    # one of the payment is not paid, hence not fully paid
    fully_paid = false
    break
  end
end

if fully_paid
  # ...
end

我们可以用**all?**来简化上面的代码,像这样:

if order.payments.all?{ |payment| payment.status == 'paid'}
  # this will be executed if all payments are paid
end

all?方法可以接收一个块,如果该块从来没有为所有的元素返回一个假的或无的值,它将返回真。

如果没有提供块,它将对这些元素进行自我检查:

order.payments.all?

# is equivalent to
order.payments.all? { |payment| payment }

这与all?相反。

none?方法接受一个块,只有当该块对所有元素都不返回真值时才返回真值:

if order.payments.none? { |payment| payment.status == 'paid' }
  # this will be executed if there is no paid payment for the order
end

如果没有提供块,它将对元素进行自我检查:

order.payments.none?

# is equivalent to
order.payments.none? { |payment| payment }

通过利用any?、all?和none?,我们可以去除循环的使用,使其更易读。