-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
100 lines (75 loc) · 2.1 KB
/
index.js
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
function filterArrayLike(array, onEach) {
const values = [];
for (let i = 0; i < array.length; ++i) {
if (onEach(array[i], i, array)) {
values.push(array[i]);
}
}
return values;
}
function getFilterIterator(iteratable) {
if(iteratable[Symbol.iterator]) {
return iteratable[Symbol.iterator]();
}
if (iteratable.constructor === Object) {
return Object.entries(iteratable)[Symbol.iterator]();
}
return null;
}
function filterIterator(iterator, iteratable, onEach) {
const values = [];
let step = iterator.next();
while (!step.done) {
if (onEach(step.value[1], step.value[0], iteratable)) {
values.push(step.value);
}
step = iterator.next();
}
return values;
}
function filterSetIterator(iterator, set, onEach) {
const values = [];
let step = iterator.next();
while (!step.done) {
if (onEach(step.value, step.value, set)) {
values.push(step.value);
}
step = iterator.next();
}
return values;
}
function createNewFromValues(instance, values) {
if (typeof instance === 'string') {
return values.join('');
}
if (instance instanceof String) {
return new instance.constructor(values.join(''));
}
if (instance.constructor === Object) {
return values.reduce((o, [k, v]) => {
o[k] = v;
return o;
}, {})
}
return new instance.constructor(values);
}
module.exports = function filter(iteratable, onEach) {
// quick win for arrays and typed arrays.
if (iteratable.filter) return iteratable.filter(onEach);
let values = [];
// array likes (eg. strings)
if (iteratable.length && iteratable[Symbol.iterator]) {
values = filterArrayLike(iteratable, onEach);
} else {
const iterator = getFilterIterator(iteratable);
if (!iterator || !iterator.next) {
throw new Error('First parameter needs to be plain Object or an iteratable.');
}
if (iteratable instanceof Set) {
values = filterSetIterator(iterator, iteratable, onEach);
} else {
values = filterIterator(iterator, iteratable, onEach);
}
}
return createNewFromValues(iteratable, values);
};