Skip to content

Commit 570ecca

Browse files
authored
Merge pull request #15 from gossie/feature/issue#14_new-operators
resolved #14
2 parents f2a9f2d + c2281a5 commit 570ecca

20 files changed

+336
-41
lines changed

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,33 @@ Some works similar to the `first`-operator except that not the element is return
6666
`every` also applies the passed function to each element. As soon as one element does not evaluate to `true` the pipe immediately returns `false`.
6767
* __none__<br />
6868
`none` also applies the passed function to each element. As soon as one element evaluates to `true` the pipe immediately returns `false`.
69+
* __reduceToSome__<br />
70+
Checks if there are two consecutive elements that fullfill the constraint passed. If a pair is found `true` is returned immediately.
71+
```typescript
72+
const result: boolean = [1, 2, 4, 5]
73+
.pipe(
74+
reduceToSome((n1: number, n2: number) => (n1+n2)%2 === 0)
75+
)
76+
```
77+
`result` would be `true` because `(2+4)%2 === 0` is `true`. The pair of 4 and 5 would not be checked.
78+
* __reduceToEvery__<br />
79+
Checks if every two consecutive elements fullfill the constraint passed. If a pair is found that does not, `false` is returned immediately.
80+
```typescript
81+
const result: boolean = [1, 3, 4, 6]
82+
.pipe(
83+
reduceToEvery((n1: number, n2: number) => (n1+n2)%2 === 0)
84+
)
85+
```
86+
`result` would be `false` because `(3+4)%2 === 0` is `false`. The pair of 4 and 6 would not be checked.
87+
* __reduceToNone__<br />
88+
Checks if no two consecutive elements fullfill the constraint passed. If a pair is found that does, `false` is returned immediately.
89+
```typescript
90+
const result: boolean = [1, 2, 4, 5]
91+
.pipe(
92+
reduceToNone((n1: number, n2: number) => (n1+n2)%2 === 0)
93+
)
94+
```
95+
`result` would be `false` because `(2+4)%2 === 0` is `true`. The pair of 4 and 5 would not be checked.
6996

7097
<a name="customoperator"></a>
7198
## Write your own operator

src/distinct.spec.ts renamed to __test__/distinct.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Operator, distinct } from './operators';
1+
import { Operator, distinct } from '../src/operators';
22

33
describe('distinct', () => {
44

__test__/every-reduce.spec.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { Operator, TerminalOperator, reduceToEvery } from '../src/operators';
2+
3+
describe('everyReduce', () => {
4+
5+
it('should be terminal', () => {
6+
const operator: Operator<number, boolean> = reduceToEvery((n1: number, n2: number) => (n1+n2)%2 === 0);
7+
expect(operator.isTerminal()).toBeTruthy();
8+
});
9+
10+
it('should have fallback value', () => {
11+
const operator: TerminalOperator<number, boolean> = reduceToEvery((n1: number, n2: number) => (n1+n2)%2 === 0);
12+
expect(operator.getFallbackValue()).toBeTruthy();
13+
});
14+
15+
it('should match criteria', () => {
16+
const operator: Operator<number, boolean> = reduceToEvery((n1: number, n2: number) => (n1+n2)%2 === 0);
17+
expect(operator.perform(1)).toEqual({
18+
value: true,
19+
done: false
20+
});
21+
22+
expect(operator.perform(3)).toEqual({
23+
value: true,
24+
done: false
25+
});
26+
});
27+
28+
it('should not match criteria', () => {
29+
const operator: Operator<number, boolean> = reduceToEvery((n1: number, n2: number) => (n1+n2)%2 === 0);
30+
expect(operator.perform(1)).toEqual({
31+
value: true,
32+
done: false
33+
});
34+
35+
expect(operator.perform(4)).toEqual({
36+
value: false,
37+
done: true
38+
});
39+
});
40+
41+
});

src/every.spec.ts renamed to __test__/every.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Operator, TerminalOperator, every } from "./operators";
1+
import { Operator, TerminalOperator, every } from "../src/operators";
22

33
describe('every', () => {
44

src/filter.spec.ts renamed to __test__/filter.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Operator, filter } from './operators';
1+
import { Operator, filter } from '../src/operators';
22

33
describe('filter', () => {
44

src/find.spec.ts renamed to __test__/find.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Operator, TerminalOperator, find } from './operators';
1+
import { Operator, TerminalOperator, find } from '../src/operators';
22

33
describe('find', () => {
44

src/flat-map.spec.ts renamed to __test__/flat-map.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { IntermediateOperator, flatMap } from './operators';
1+
import { IntermediateOperator, flatMap } from '../src/operators';
22

33
describe('flatMap', () => {
44

src/index-no-overwrite.spec.ts renamed to __test__/index-no-overwrite.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import './polyfill.mock';
2-
import './index';
2+
import '../src/index';
33

44
describe('pipe already exists', () => {
55
it('should not override pipe when already set', () => {

src/index.spec.ts renamed to __test__/index.spec.ts

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import './index';
2-
import { filter, map, flatMap, distinct, find, some, every, none } from './operators';
1+
import '../src/index';
2+
import { filter, map, flatMap, distinct, find, some, every, none, reduceToEvery, reduceToSome, reduceToNone } from '../src/operators';
33

44
describe('pipe', () => {
55

@@ -32,7 +32,7 @@ describe('pipe', () => {
3232
});
3333

3434
it('should filter', () => {
35-
const result: Array<string> = [0, 1, 1, 2, 3, 4, 2, 5, 6, 7, 2, 8, 9]
35+
const result: Array<number> = [0, 1, 1, 2, 3, 4, 2, 5, 6, 7, 2, 8, 9]
3636
.pipe(
3737
filter((n: number) => n%2 == 0)
3838
);
@@ -72,7 +72,7 @@ describe('pipe', () => {
7272
});
7373

7474
it('should pipe and return true because some elements match criteria', () => {
75-
const result: number = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
75+
const result: boolean = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
7676
.pipe(
7777
map((n: string) => parseInt(n)),
7878
some((n: number) => n > 5 && n < 10)
@@ -82,7 +82,7 @@ describe('pipe', () => {
8282
});
8383

8484
it('should pipe and return false because no element matches criteria', () => {
85-
const result: number = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
85+
const result: boolean = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
8686
.pipe(
8787
map((n: string) => parseInt(n)),
8888
some((n: number) => n >= 10)
@@ -92,7 +92,7 @@ describe('pipe', () => {
9292
});
9393

9494
it('should pipe and return true because all elements match criteria', () => {
95-
const result: number = ['2', '4', '6', '8', '10', '12', '14', '16', '18', '20']
95+
const result: boolean = ['2', '4', '6', '8', '10', '12', '14', '16', '18', '20']
9696
.pipe(
9797
map((n: string) => parseInt(n)),
9898
every((n: number) => n%2 === 0)
@@ -102,7 +102,7 @@ describe('pipe', () => {
102102
});
103103

104104
it('should pipe and return false because not all elements match criteria', () => {
105-
const result: number = ['2', '4', '6', '8', '11', '12', '14', '16', '18', '20']
105+
const result: boolean = ['2', '4', '6', '8', '11', '12', '14', '16', '18', '20']
106106
.pipe(
107107
map((n: string) => parseInt(n)),
108108
every((n: number) => n%2 === 0)
@@ -112,7 +112,7 @@ describe('pipe', () => {
112112
});
113113

114114
it('should pipe and return true because all elements do not match criteria', () => {
115-
const result: number = ['3', '5', '7', '9', '11', '13', '15', '17', '19', '21']
115+
const result: boolean = ['3', '5', '7', '9', '11', '13', '15', '17', '19', '21']
116116
.pipe(
117117
map((n: string) => parseInt(n)),
118118
none((n: number) => n%2 === 0)
@@ -122,7 +122,7 @@ describe('pipe', () => {
122122
});
123123

124124
it('should pipe and return false because not all elements match criteria', () => {
125-
const result: number = ['3', '5', '7', '9', '12', '13', '15', '17', '19', '21']
125+
const result: boolean = ['3', '5', '7', '9', '12', '13', '15', '17', '19', '21']
126126
.pipe(
127127
map((n: string) => parseInt(n)),
128128
none((n: number) => n%2 === 0)
@@ -151,7 +151,7 @@ describe('pipe', () => {
151151

152152
describe('flatMap', () => {
153153
it('should pipe with flatMap as last operator', () => {
154-
const result: number = ['1', '3', '5', '7', '9']
154+
const result: Array<number> = ['1', '3', '5', '7', '9']
155155
.pipe(
156156
map((s: string) => parseInt(s)),
157157
flatMap((n: number) => [n, n+1])
@@ -161,7 +161,7 @@ describe('pipe', () => {
161161
});
162162

163163
it('should pipe with flatMap as intermediate operator', () => {
164-
const result: number = ['1', '3', '5', '7', '9']
164+
const result: Array<number> = ['1', '3', '5', '7', '9']
165165
.pipe(
166166
map((s: string) => parseInt(s)),
167167
flatMap((n: number) => [n, n+1]),
@@ -184,7 +184,7 @@ describe('pipe', () => {
184184
});
185185

186186
it('should pipe with flatMap as intermediate operator and filter in the end', () => {
187-
const result: boolean = ['1', '3', '5', '7', '9']
187+
const result: Array<number> = ['1', '3', '5', '7', '9']
188188
.pipe(
189189
map((s: string) => parseInt(s)),
190190
flatMap((n: number) => [n, n+1]),
@@ -196,6 +196,70 @@ describe('pipe', () => {
196196

197197
});
198198

199+
describe('reducer', () => {
200+
201+
it('should successfully reduce to every', () => {
202+
const result: boolean = ['1', '3', '5', '7', '9']
203+
.pipe(
204+
map((s: string) => parseInt(s)),
205+
reduceToEvery((n1: number, n2: number) => (n1+n2)%2 === 0)
206+
);
207+
208+
expect(result).toBeTruthy();
209+
});
210+
211+
it('should fail to reduce to every', () => {
212+
const result: boolean = ['1', '3', '5', '6', '9']
213+
.pipe(
214+
map((s: string) => parseInt(s)),
215+
reduceToEvery((n1: number, n2: number) => (n1+n2)%2 === 0)
216+
);
217+
218+
expect(result).toBeFalsy();
219+
});
220+
221+
it('should successfully reduce to some', () => {
222+
const result: boolean = ['1', '2', '5', '7', '9']
223+
.pipe(
224+
map((s: string) => parseInt(s)),
225+
reduceToSome((n1: number, n2: number) => (n1+n2)%2 === 0)
226+
);
227+
228+
expect(result).toBeTruthy();
229+
});
230+
231+
it('should fail to reduce to some', () => {
232+
const result: boolean = ['1', '2', '5', '6', '9']
233+
.pipe(
234+
map((s: string) => parseInt(s)),
235+
reduceToSome((n1: number, n2: number) => (n1+n2)%2 === 0)
236+
);
237+
238+
expect(result).toBeFalsy();
239+
});
240+
241+
it('should successfully reduce to none', () => {
242+
const result: boolean = ['1', '2', '5', '6', '9']
243+
.pipe(
244+
map((s: string) => parseInt(s)),
245+
reduceToNone((n1: number, n2: number) => (n1+n2)%2 === 0)
246+
);
247+
248+
expect(result).toBeTruthy();
249+
});
250+
251+
it('should fail to reduce to none', () => {
252+
const result: boolean = ['1', '2', '5', '7', '9']
253+
.pipe(
254+
map((s: string) => parseInt(s)),
255+
reduceToNone((n1: number, n2: number) => (n1+n2)%2 === 0)
256+
);
257+
258+
expect(result).toBeFalsy();
259+
});
260+
261+
})
262+
199263
});
200264

201265
})

src/map.spec.ts renamed to __test__/map.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Operator, map } from './operators';
1+
import { Operator, map } from '../src/operators';
22

33
describe('map', () => {
44

0 commit comments

Comments
 (0)