Adding anySatisfy, noneSatisfy to Sequence

Adding anySatisfy, noneSatisfy to Sequence

Introduction

I propose to add two methods to Sequence

  • anySatisfy
  • noneSatisfy

Motivation

anySatisfy: we need to determine whether a sequence meets a condition by iterating each element until one meets the predicate. When an element meets the predicate, the iteration exits early.

noneSatisfy: we need to determine whether a sequence meets a condition by iterating every element and testing a predicate. When an element does not meet the predicate, the iteration exits early.

Proposed solution

public extension Sequence {
func anySatisfy(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
  for element in self {
    if try predicate(element) { return true }
  }
  return false
}

  func noneSatisfy(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
    try !anySatisfy(predicate)
  }
}

This allows to write efficient, readable code like this:

struct Item {
  var inProgress: Bool
}

func test_item_sequence_is_in_progress() {
  var items = [Item](repeating: .init(inProgress: false), count: 10)
  let randomIndex = (0..<items.count).randomElement()!
  items[randomIndex].inProgress = true
  let itemsInProgress = items.anySatisfy(\.inProgress)
  XCTAssert(itemsInProgress)
}

func test_item_sequence_not_started() {
  let items = [Item](repeating: .init(inProgress: false), count: 10)
  let itemsComplete = items.noneSatisfy(\.inProgress)
  XCTAssert(itemsComplete)
}

func test_item_sequence_complete() {
  let items = [Item](repeating: .init(inProgress: true), count: 10)
  let itemsComplete = items.allSatisfy(\.inProgress)
  XCTAssert(itemsComplete)
}

Your anySatisfy is functionally identical to the existing contains(where:) method. noneSatisfy is then just the Boolean inverse of that function, which I don’t think is sufficiently complex enough to warrant adding to the standard library.

7 Likes

The inverse exists as well under the name allSatisfy: allSatisfy(_:) | Apple Developer Documentation

It was introduced with https://github.com/apple/swift-evolution/blob/main/proposals/0207-containsOnly.md

1 Like

I have used anyContains(where:) for many years that I haven't realized the Standard Library now provides contains(where:).
noneSatisfy is an inverse to anySatisfy.
I posted an allSatisfy unit test just to improve clarity on the other unit tests' intent.
I really appreciate the feedback.