Skip to content

Commit 25b2fd8

Browse files
committed
add count(where:) and tests
1 parent 672433c commit 25b2fd8

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed

stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,25 @@ public struct FilterTest {
140140
}
141141
}
142142

143+
public struct PredicateCountTest {
144+
public let expected: Int
145+
public let sequence: [Int]
146+
public let includeElement: (Int) -> Bool
147+
public let loc: SourceLoc
148+
149+
public init(
150+
_ expected: Int,
151+
_ sequence: [Int],
152+
_ includeElement: @escaping (Int) -> Bool,
153+
file: String = #file, line: UInt = #line
154+
) {
155+
self.expected = expected
156+
self.sequence = sequence
157+
self.includeElement = includeElement
158+
self.loc = SourceLoc(file, line, comment: "test data")
159+
}
160+
}
161+
143162
public struct FindTest {
144163
public let expected: Int?
145164
public let element: MinimalEquatableValue
@@ -522,6 +541,21 @@ public let filterTests = [
522541
),
523542
]
524543

544+
public let predicateCountTests = [
545+
PredicateCountTest(
546+
0, [],
547+
{ _ -> Bool in expectUnreachable(); return true }),
548+
549+
PredicateCountTest(0, [ 0, 30, 10, 90 ], { _ -> Bool in false }),
550+
PredicateCountTest(
551+
4, [ 0, 30, 10, 90 ], { _ -> Bool in true }
552+
),
553+
PredicateCountTest(
554+
3, [ 0, 30, 10, 90 ], { (x: Int) -> Bool in x % 3 == 0 }
555+
),
556+
]
557+
558+
525559
public let findTests = [
526560
FindTest(
527561
expected: nil,

stdlib/public/core/SequenceAlgorithms.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,52 @@ extension Sequence where Element : Equatable {
516516
}
517517
}
518518

519+
//===----------------------------------------------------------------------===//
520+
// count(where:)
521+
//===----------------------------------------------------------------------===//
522+
523+
extension Sequence {
524+
/// Returns a Int value indicating how many elements in the sequence
525+
/// satisfy the given predicate.
526+
///
527+
/// You can use the predicate to check for an element of a type that
528+
/// doesn't conform to the `Equatable` protocol, such as the
529+
/// `HTTPResponse` enumeration in this example.
530+
///
531+
/// enum HTTPResponse {
532+
/// case ok
533+
/// case error(Int)
534+
/// }
535+
///
536+
/// let responses: [HTTPResponse] = [.ok, .error(500), .error(404)]
537+
/// let numberOfErrors = responses.count { element in
538+
/// if case .error = element {
539+
/// return true
540+
/// } else {
541+
/// return false
542+
/// }
543+
/// }
544+
/// // 'numberOfErrors' == 2
545+
///
546+
/// - Parameter predicate: A closure that takes an element of the sequence
547+
/// as its argument and returns a Boolean value that indicates whether
548+
/// the passed element should be included in the count.
549+
/// - Returns: a value indicating how many elements in the sequence
550+
/// satisfy the given predicate.
551+
@inlinable
552+
public func count(
553+
where predicate: (Element) throws -> Bool
554+
) rethrows -> Int {
555+
var count = 0
556+
for e in self {
557+
if try predicate(e) {
558+
count += 1
559+
}
560+
}
561+
return count
562+
}
563+
}
564+
519565
//===----------------------------------------------------------------------===//
520566
// reduce()
521567
//===----------------------------------------------------------------------===//

validation-test/stdlib/SequenceType.swift.gyb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,21 @@ SequenceTypeTests.test("contains/Predicate") {
614614
}
615615
}
616616

617+
//===----------------------------------------------------------------------===//
618+
// count(where:)
619+
//===----------------------------------------------------------------------===//
620+
621+
SequenceTypeTests.test("count/Predicate") {
622+
for test in predicateCountTests {
623+
let s = MinimalSequence<OpaqueValue<Int>>(
624+
elements: test.sequence.map { OpaqueValue($0) })
625+
expectEqual(
626+
test.expected,
627+
s.count(where: { test.includeElement($0.value) }),
628+
stackTrace: SourceLocStack().with(test.loc))
629+
}
630+
}
631+
617632
//===----------------------------------------------------------------------===//
618633
// reduce()
619634
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)