Skip to content

Instantly share code, notes, and snippets.

@khanlou
Last active November 4, 2019 23:14
Show Gist options
  • Save khanlou/99066a5a0e9ab59755ef to your computer and use it in GitHub Desktop.
Save khanlou/99066a5a0e9ab59755ef to your computer and use it in GitHub Desktop.
`any`, `all`, `none`, `first`, and `count` on SequenceType in Swift
import Foundation
extension SequenceType {
@warn_unused_result
func any(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Bool {
for element in self {
let result = try predicate(element)
if result {
return true
}
}
return false
}
@warn_unused_result
func all(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Bool {
for element in self {
let result = try predicate(element)
if !result {
return false
}
}
return true
}
@warn_unused_result
func none(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Bool {
for element in self {
let result = try predicate(element)
if result {
return false
}
}
return true
}
//part of the standard library as of Swift 3, as `first(where:)`
@warn_unused_result
func first(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Self.Generator.Element? {
for element in self {
if try predicate(element) {
return element
}
}
return nil
}
@warn_unused_result
func count(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Int {
var count = 0
for element in self {
if try predicate(element) {
count += 1
}
}
return count
}
}
extension Sequence {
func any(_ predicate: (Self.Iterator.Element) throws -> Bool) rethrows -> Bool {
for element in self {
let result = try predicate(element)
if result {
return true
}
}
return false
}
func all(_ predicate: (Self.Iterator.Element) throws -> Bool) rethrows -> Bool {
for element in self {
let result = try predicate(element)
if !result {
return false
}
}
return true
}
func none(_ predicate: (Self.Iterator.Element) throws -> Bool) rethrows -> Bool {
let result = try self.any(predicate: predicate)
return !result
}
func count(_ predicate: (Self.Iterator.Element) throws -> Bool) rethrows -> Int {
var count = 0
for element in self {
if try predicate(element) {
count += 1
}
}
return count
}
}
extension Sequence {
func any(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
for element in self {
if try predicate(element) {
return true
}
}
return false
}
func all(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
for element in self {
if try !predicate(element) {
return false
}
}
return true
}
func none(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
return try !self.any(predicate)
}
func count(_ predicate: (Element) throws -> Bool) rethrows -> Int {
var count = 0
for element in self {
if try predicate(element) {
count += 1
}
}
return count
}
}
@vlastachu
Copy link

Cool. I hope find this in standard lib

@alexandre-g
Copy link

Thanks for sharing

@mwaterfall
Copy link

@khanlou Great collection. I initially thought it could be made more concise by using some of the other built-in sequence functions, and it does indeed reduce the code a fair bit which is quite nice, but the problem is it's just not as readable as the original.

I don't know what I prefer… which is a problem that's really interesting to ponder over.

extension Sequence {
	func any(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
		return try self.contains(where: { try predicate($0) == true })
	}

	func all(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
		let containsFailed = try self.contains(where: { try predicate($0) == false })
		return !containsFailed
	}

	func none(_ predicate: (Element) throws -> Bool) rethrows -> Bool {
		let result = try self.any(predicate)
		return !result
	}

	func count(_ predicate: (Element) throws -> Bool) rethrows -> Int {
		return try self.reduce(0, { (result, element) in
			return result + (try predicate(element) ? 1 : 0)
		})
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment