-
Notifications
You must be signed in to change notification settings - Fork 7
/
filter.ts
83 lines (72 loc) · 2.14 KB
/
filter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Copyright (c) 2020 Jozty. All rights reserved. MIT license.
import type { FunctorWithArLk, Obj, PH, Predicate1 } from './utils/types.ts';
import {
isArray,
isArrayLike,
isIterable,
isIterator,
isObject,
} from './utils/is.ts';
import { reduce } from './reduce.ts';
import { throwFunctorError } from './utils/throw.ts';
import { dispatch } from './utils/dispatch.ts';
import FilterTransformer from './utils/Transformers/filter.ts';
import curryN from './utils/curry_n.ts';
// @types
type Filter_1<T> = (predicate: Predicate1<T>) => T[] | Partial<Obj<T>>;
type Filter_2<T> = (
functor: FunctorWithArLk<T> | Obj<T>,
) => T[] | Partial<Obj<T>>;
type Filter =
& (<T>(predicate: Predicate1<T>) => Filter_2<T>)
& (<T>(predicate: PH, functor: FunctorWithArLk<T> | Obj<T>) => Filter_1<T>)
& (<T>(
predicate: Predicate1<T>,
functor: FunctorWithArLk<T> | Obj<T>,
) => T[] | Partial<Obj<T>>);
function _objectFilter<T>(predicate: Predicate1<T>, functor: Obj<T>) {
return reduce(
(acc: Obj<T>, key: string) => {
if (predicate(functor[key])) acc[key] = functor[key];
return acc;
},
{},
Object.keys(functor),
);
}
function _functorFilter<T>(
predicate: Predicate1<T>,
functor: FunctorWithArLk<T>,
): T[] {
return reduce(
(acc: T[], value: T) => {
if (predicate(value)) acc.push(value);
return acc;
},
[],
functor,
);
}
function _filter<T = unknown>(
predicate: Predicate1<T>,
functor: FunctorWithArLk<T> | Obj<T>,
): T[] | Partial<Obj<T>> {
if (isArray(functor)) return (functor as T[]).filter(predicate) as T[];
if (
isArrayLike(functor) ||
isIterable(functor) ||
isIterator(functor)
) {
return _functorFilter(predicate, functor);
}
if (isObject(functor)) return _objectFilter(predicate, functor);
throw throwFunctorError();
}
const dispatchedFilter = dispatch(FilterTransformer, _filter);
/**
* Filters the those elements from `functor` that satisfies `predicate`.
* The `functor` may be an array/object/iterable/iterator.
*
* Acts as a transducer if a transformer is passed in place of `functor`
*/
export const filter: Filter = curryN(2, dispatchedFilter);