Skip to content

Commit 674ee1d

Browse files
polonezfreak4pc
authored andcommitted
Add count operator (#190)
1 parent e4da6ad commit 674ee1d

File tree

8 files changed

+335
-3
lines changed

8 files changed

+335
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ master
99
- rolled `map(to:)` back to `mapTo(_:)` for `SharedSequenceConvertibleType`
1010
- added `unwrap()` operator for SharedSequence
1111
- added `apply(_:)` for `Single`
12+
- added `count` operator
1213

1314
3.3.0
1415
-----

Playground/RxSwiftExtPlayground.playground/Pages/Index.xcplaygroundpage/Contents.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
- [Observable.fromAsync()](fromAsync) constructor, translates an async function that returns data through a completionHandler in a function that returns data through an Observable
4444
- [ofType()](ofType) operator, filters the elements of an observable sequence, if that is an instance of the supplied type.
4545
- [toSortedArray()](mapMany) operator, converts an Observable into another Observable that emits the whole sequence as a single array sorted using the provided closure and then terminates.
46+
- [count(predicate)](count) operator, counts the number of items emitted by an Observable. If predicate exists, then counts the number of items satisfying it.
4647
- **UIViewPropertyAnimator** [animate()](UIViewPropertyAnimator.animate) operator, returns a Completable that completes as soon as the animation ends.
4748
- **UIViewPropertyAnimator** [fractionComplete](UIViewPropertyAnimator.fractionComplete) binder, provides a reactive way to bind to `UIViewPropertyAnimator.fractionComplete`.
4849
*/
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*:
2+
> # IMPORTANT: To use `RxSwiftExtPlayground.playground`, please:
3+
4+
1. Make sure you have [Carthage](https://github.com/Carthage/Carthage) installed
5+
1. Fetch Carthage dependencies from shell: `carthage bootstrap --platform ios`
6+
1. Build scheme `RxSwiftExtPlayground` scheme for a simulator target
7+
1. Choose `View > Show Debug Area`
8+
*/
9+
10+
//: [Previous](@previous)
11+
12+
import RxSwift
13+
import RxSwiftExt
14+
15+
/*:
16+
## count
17+
18+
Count the number of items emitted by an Observable
19+
- seealso: [count operator on reactivex.io](http://reactivex.io/documentation/operators/count.html)
20+
- parameter predicate: predicate determines what elements to be counted.
21+
22+
- returns: An Observable sequence containing a value that represents how many elements in the specified observable sequence satisfy a condition if provided, else the count of items.
23+
24+
*/
25+
26+
example("count") {
27+
28+
// count even number in the sequence
29+
let _ = Observable.from([1...10])
30+
.count { $0 % 2 == 0 }
31+
.subscribe(onNext: {
32+
print ($0)
33+
})
34+
35+
}
36+
37+
//: [Next](@next)

Playground/RxSwiftExtPlayground.playground/contents.xcplayground

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<page name='apply'/>
66
<page name='cascade'/>
77
<page name='catchErrorJustComplete'/>
8+
<page name='count'/>
89
<page name='distinct'/>
910
<page name='ignore'/>
1011
<page name='not'/>
@@ -22,5 +23,10 @@
2223
<page name='nwise'/>
2324
<page name='zipWith'/>
2425
<page name='ofType'/>
26+
<page name='mapMany'/>
27+
<page name='toSortedArray'/>
28+
<page name='UIViewPropertyAnimator.animate'/>
29+
<page name='UIViewPropertyAnimator.fractionComplete'/>
30+
<page name='withUnretained'/>
2531
</pages>
26-
</playground>
32+
</playground>

Readme.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ These operators are much like the RxSwift & RxCocoa core operators, but provide
8080
* [Observable.fromAsync](#fromasync)
8181
* [Observable.zip(with:)](#zipwith)
8282
* [withUnretained](#withunretained)
83+
* [count](#count)
8384

8485
There are two more available operators for `materialize()`'d sequences:
8586

@@ -128,7 +129,7 @@ Ignore specific elements.
128129
```
129130
next(One)
130131
next(Three)
131-
completed
132+
completed
132133
```
133134

134135
#### ignoreWhen
@@ -510,7 +511,7 @@ observableService("Foo", 0)
510511
Convenience version of `Observable.zip(_:)`. Merges the specified observable sequences into one observable sequence by using the selector function whenever all
511512
of the observable sequences have produced an element at a corresponding index.
512513

513-
```
514+
```swift
514515
let first = Observable.from(numbers)
515516
let second = Observable.from(strings)
516517

@@ -582,6 +583,21 @@ next((Test Class, 13))
582583
completed
583584
```
584585

586+
#### [count](http://reactivex.io/documentation/operators/count.html)
587+
588+
Emits the number of items emitted by an Observable once it terminates with no errors. If a predicate is given, only elements matching the predicate will be counted.
589+
590+
```swift
591+
Observable.from([1, 2, 3, 4, 5, 6])
592+
.count { $0 % 2 == 0 }
593+
.subscribe()
594+
```
595+
596+
```
597+
next(3)
598+
completed
599+
```
600+
585601
Reactive Extensions details
586602
===========
587603

RxSwiftExt.xcodeproj/project.pbxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@
150150
98309EAF1EDF14AC00BD07D9 /* flatMapSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98309EAE1EDF14AC00BD07D9 /* flatMapSync.swift */; };
151151
98309EB11EDF159500BD07D9 /* filterMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98309EB01EDF159500BD07D9 /* filterMap.swift */; };
152152
98309EB41EDF167300BD07D9 /* FilterMapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98309EB21EDF161700BD07D9 /* FilterMapTests.swift */; };
153+
B69B45492190C27D00F30418 /* count.swift in Sources */ = {isa = PBXBuildFile; fileRef = B69B45482190C27D00F30418 /* count.swift */; };
154+
B69B454A2190C3AE00F30418 /* count.swift in Sources */ = {isa = PBXBuildFile; fileRef = B69B45482190C27D00F30418 /* count.swift */; };
155+
B69B454B2190C3AF00F30418 /* count.swift in Sources */ = {isa = PBXBuildFile; fileRef = B69B45482190C27D00F30418 /* count.swift */; };
156+
B69B454E2190C3CC00F30418 /* CountTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B69B454C2190C3BC00F30418 /* CountTests.swift */; };
157+
B69B454F2190C3CC00F30418 /* CountTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B69B454C2190C3BC00F30418 /* CountTests.swift */; };
158+
B69B45502190C3CD00F30418 /* CountTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B69B454C2190C3BC00F30418 /* CountTests.swift */; };
153159
BF515CE01F3F370600492640 /* curry.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF515CDF1F3F370600492640 /* curry.swift */; };
154160
BF515CE21F3F371600492640 /* fromAsync.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF515CE11F3F371600492640 /* fromAsync.swift */; };
155161
BF515CE51F3F3AF400492640 /* FromAsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF515CE31F3F3AC900492640 /* FromAsyncTests.swift */; };
@@ -330,6 +336,8 @@
330336
98309EB01EDF159500BD07D9 /* filterMap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = filterMap.swift; path = Source/RxSwift/filterMap.swift; sourceTree = SOURCE_ROOT; };
331337
98309EB21EDF161700BD07D9 /* FilterMapTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilterMapTests.swift; sourceTree = "<group>"; };
332338
9DAB77851D67639C007E85BC /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Source/Info.plist; sourceTree = SOURCE_ROOT; };
339+
B69B45482190C27D00F30418 /* count.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = count.swift; sourceTree = "<group>"; };
340+
B69B454C2190C3BC00F30418 /* CountTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountTests.swift; sourceTree = "<group>"; };
333341
BF515CDF1F3F370600492640 /* curry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = curry.swift; path = Source/Tools/curry.swift; sourceTree = SOURCE_ROOT; };
334342
BF515CE11F3F371600492640 /* fromAsync.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = fromAsync.swift; path = Source/RxSwift/fromAsync.swift; sourceTree = SOURCE_ROOT; };
335343
BF515CE31F3F3AC900492640 /* FromAsyncTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FromAsyncTests.swift; sourceTree = "<group>"; };
@@ -482,6 +490,7 @@
482490
5386079A1E6F334B000361DE /* apply.swift */,
483491
5386079B1E6F334B000361DE /* cascade.swift */,
484492
5386079C1E6F334B000361DE /* catchErrorJustComplete.swift */,
493+
B69B45482190C27D00F30418 /* count.swift */,
485494
5386079D1E6F334B000361DE /* distinct.swift */,
486495
98309EB01EDF159500BD07D9 /* filterMap.swift */,
487496
98309EAE1EDF14AC00BD07D9 /* flatMapSync.swift */,
@@ -518,6 +527,7 @@
518527
538607BB1E6F367A000361DE /* ApplyTests.swift */,
519528
538607BC1E6F367A000361DE /* CascadeTests.swift */,
520529
538607BD1E6F367A000361DE /* CatchErrorJustCompleteTests.swift */,
530+
B69B454C2190C3BC00F30418 /* CountTests.swift */,
521531
538607BE1E6F367A000361DE /* DistinctTests.swift */,
522532
98309EB21EDF161700BD07D9 /* FilterMapTests.swift */,
523533
BF515CE31F3F3AC900492640 /* FromAsyncTests.swift */,
@@ -977,6 +987,7 @@
977987
3DBDE5FC1FBBAE3A00DF47F9 /* and.swift in Sources */,
978988
8CF5F8B3202D6C5F00C1BA97 /* mapAt.swift in Sources */,
979989
538607B31E6F334B000361DE /* not.swift in Sources */,
990+
B69B45492190C27D00F30418 /* count.swift in Sources */,
980991
538607AD1E6F334B000361DE /* distinct.swift in Sources */,
981992
D7C72A421FDC5D8F00EAAAAB /* nwise.swift in Sources */,
982993
538607B61E6F334B000361DE /* pausable.swift in Sources */,
@@ -1005,6 +1016,7 @@
10051016
538607E01E6F36A9000361DE /* CascadeTests.swift in Sources */,
10061017
53F336EA1E70D59000D35D38 /* DistinctTests+RxCocoa.swift in Sources */,
10071018
98309EB41EDF167300BD07D9 /* FilterMapTests.swift in Sources */,
1019+
B69B454E2190C3CC00F30418 /* CountTests.swift in Sources */,
10081020
6662395E1E9E0950009BB134 /* Materialized+elementsTests.swift in Sources */,
10091021
538607E81E6F36A9000361DE /* NotTests.swift in Sources */,
10101022
BF515CE51F3F3AF400492640 /* FromAsyncTests.swift in Sources */,
@@ -1045,6 +1057,7 @@
10451057
62512C7A1F0EAF950083A89F /* unwrap.swift in Sources */,
10461058
780CB21620A0ED1C00FD3F39 /* toSortedArray.swift in Sources */,
10471059
62512C741F0EAF950083A89F /* ObservableType+Weak.swift in Sources */,
1060+
B69B454A2190C3AE00F30418 /* count.swift in Sources */,
10481061
62512C6F1F0EAF950083A89F /* ignoreErrors.swift in Sources */,
10491062
62512C701F0EAF950083A89F /* ignoreWhen.swift in Sources */,
10501063
789682E720408A7500545396 /* mapAt.swift in Sources */,
@@ -1088,6 +1101,7 @@
10881101
62512C961F0EB1850083A89F /* IgnoreErrorsTests.swift in Sources */,
10891102
BF515CE61F3F3AF500492640 /* FromAsyncTests.swift in Sources */,
10901103
62512CA41F0EB1850083A89F /* FilterMapTests.swift in Sources */,
1104+
B69B454F2190C3CC00F30418 /* CountTests.swift in Sources */,
10911105
D7C72A3F1FDC5C5D00EAAAAB /* NwiseTests.swift in Sources */,
10921106
8CF5F8B0202D62AD00C1BA97 /* MapAtTests.swift in Sources */,
10931107
62512C8F1F0EB17A0083A89F /* DistinctTests+RxCocoa.swift in Sources */,
@@ -1122,6 +1136,7 @@
11221136
E39C41EB1F18B08A007F2ACD /* unwrap.swift in Sources */,
11231137
780CB21720A0ED1C00FD3F39 /* toSortedArray.swift in Sources */,
11241138
E39C41E51F18B08A007F2ACD /* ObservableType+Weak.swift in Sources */,
1139+
B69B454B2190C3AF00F30418 /* count.swift in Sources */,
11251140
E39C41E01F18B08A007F2ACD /* ignoreErrors.swift in Sources */,
11261141
E39C41E11F18B08A007F2ACD /* ignoreWhen.swift in Sources */,
11271142
789682E820408A7700545396 /* mapAt.swift in Sources */,
@@ -1165,6 +1180,7 @@
11651180
E39C42121F18B13E007F2ACD /* FilterMapTests.swift in Sources */,
11661181
BF515CE71F3F3AF500492640 /* FromAsyncTests.swift in Sources */,
11671182
E39C41FF1F18B13A007F2ACD /* NotTests+RxCocoa.swift in Sources */,
1183+
B69B45502190C3CD00F30418 /* CountTests.swift in Sources */,
11681184
D7C72A401FDC5C5D00EAAAAB /* NwiseTests.swift in Sources */,
11691185
8CF5F8B1202D62AE00C1BA97 /* MapAtTests.swift in Sources */,
11701186
E39C42011F18B13E007F2ACD /* CascadeTests.swift in Sources */,

Source/RxSwift/count.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// count.swift
3+
// RxSwiftExt-iOS
4+
//
5+
// Created by Fred on 06/11/2018.
6+
// Copyright © 2018 RxSwiftCommunity. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import RxSwift
11+
12+
extension Observable {
13+
/**
14+
Count the number of items emitted by an Observable
15+
- seealso: [count operator on reactivex.io](http://reactivex.io/documentation/operators/count.html)
16+
- returns: An Observable sequence containing a value that represents how many elements in the specified observable sequence satisfy a condition if provided, else the count of items.
17+
*/
18+
public func count() -> Observable<Int> {
19+
return reduce(0) { count, _ in count + 1 }
20+
}
21+
/**
22+
Count the number of items emitted by an Observable
23+
- seealso: [count operator on reactivex.io](http://reactivex.io/documentation/operators/count.html)
24+
- parameter predicate: predicate determines what elements to be counted.
25+
26+
- returns: An Observable sequence containing a value that represents how many elements in the specified observable sequence satisfy a condition if provided, else the count of items.
27+
*/
28+
public func count(_ predicate: @escaping (Element) throws -> Bool) -> Observable<Int> {
29+
return filter(predicate).count()
30+
}
31+
}

0 commit comments

Comments
 (0)