-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmyReduce.html
More file actions
156 lines (152 loc) · 7.15 KB
/
myReduce.html
File metadata and controls
156 lines (152 loc) · 7.15 KB
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<script src="..\my-jsArrayMethods\simpletest.js"></script>
<script>
// The reduce() method applies a function against an accumulator and each element in the array (from left to right).
// Result is reduced to a single value.
// Parameters
// originalArray.
// callback: Function to execute on each element in the array, taking four arguments:
// accumulator
// The accumulator accumulates the callback's return values;
// it is the accumulated value previously returned in the last invocation of the callback, or initialValue, if supplied (see below).
// currentValue
// The current element being processed in the array.
// currentIndexOptional
// The index of the current element being processed in the array.
// Starts at index 0, if an initialValue is provided, and at index 1 otherwise.
// arrayOptional
// The array reduce() was called upon.
// initialValueOptional
// Value passed into callback on first iteration.
// If no initial value is supplied, the 1st element in the array will be used; iteration starts with 2nd el.
// Calling reduce() on an empty array without an initial value is an error.
// Return value
// The value that results from the reduction.
// Notes:
// If initialValue isn't provided, reduce() will execute the callback function starting at index 1, using the first index as initialValue.
// If initialValue is provided, it will start at index 0.
// If the array is empty and no initialValue is provided, TypeError will be thrown.
// If the array has only one element (regardless of position) and no initialValue is provided...
// or if initialValue is provided but the array is empty, ...
// ...the solo value will be returned without calling callback.
function myReduce(originalArray, callback, initialValue) {
var startingIndex = 0;
var reducedValue;
// if no initialValue
if (arguments.length < 3) {
// If originalArray is empty, throw TypeError.
if (Object.keys(originalArray).length === 0) {
throw new TypeError ('Reduce of empty array with no initial value');
}
// If originalArray has only one element, just return it.
if (Object.keys(originalArray).length === 1) {
return originalArray[0];
}
while (startingIndex in originalArray === false && startingIndex < originalArray.length) {
startingIndex ++;
}
reducedValue = originalArray[startingIndex];
startingIndex++;
} else {
// has initialValue
if (Object.keys(originalArray).length === 0) {
return initialValue;
}
reducedValue = initialValue;
}
for (var i = startingIndex; i < originalArray.length; i ++) {
if (i in originalArray) {
reducedValue = callback(reducedValue, originalArray[i], i, originalArray);
}
}
return reducedValue;
}
tests({
'It should accept an optional initialValue to be used as the accumulator.' : function() {
var testInitialValue = myReduce([], function() {}, 36);
eq(testInitialValue, 36);
},
'If initialValue, callback should run originalArray.length times.': function() {
callbackCounter = 0;
myReduce([1, 2, 3], function(){
callbackCounter ++;
}, 1);
eq(callbackCounter, 3);
},
'If no initialValue, callback should run (originalArray.length - 1) times.': function() {
callbackCounter = 0;
myReduce([1, 2, 3], function() {
callbackCounter ++;
});
eq(callbackCounter, 2);
},
'If no initialValue, reducedValue should start as originalArray[0].' : function() {
var testNoInitialValue = myReduce([1], function(acc, currentValue) {});
eq(testNoInitialValue, 1);
},
'It should pass callback the current value of the element being evaluated.' : function() {
var originalArray = [2];
myReduce(originalArray, function(acc, currentValue) {
for (i = 0; i < originalArray.length; i ++) {
eq(originalArray[i], 2);
}
});
},
'It should pass callback an optional index of the el being evaluated.' : function() {
var originalArray = [3];
myReduce(originalArray, function(acc, currentValue, index) {
for (var i = 0; i < originalArray.length; i ++) {
eq(index, 0);
}
});
},
'It should pass callback the array being evaluated.' : function() {
var originalArray = [1, 2, 3];
myReduce(originalArray, function(acc, currentValue, index, testArray) {
eq(testArray, originalArray);
});
},
'It should reduce originalArray to single value based on callback.' : function() {
var originalArray = [1, 2, 3];
var reducedArrayValue = myReduce(originalArray, function(acc, num) {
return acc + num;
});
eq(reducedArrayValue, 6)
},
'If initialValue, callback should not run on holes in the originalArray.' : function() {
var originalArray = [, 2, , 4, ,];
var reducedArrayValue = myReduce(originalArray, function(acc, num) {
return acc + num;
}, 0);
eq(reducedArrayValue, 6);
},
'If no initialValue, callback should not run on holes at beginning of originalArray.' : function() {
var originalArray = [, 2, , 4, ,];
var reducedArrayValue = myReduce(originalArray, function(acc, num) {
return acc + num;
});
eq(reducedArrayValue, 6);
},
'If array is empty, and no initialValue, throw TypeError.' : function() {
var isTypeError = false;
try {
myReduce([], function() {});
} catch(e) {
isTypeError = (e instanceof TypeError);
}
eq(isTypeError, true);
},
'If array is empty, and initialValue, it should return initialValue without calling callback.': function() {
var numberOfTimesCallbackHasRun = 0;
var initialValue = 0;
var reducedValue = myReduce([,,], function() {
numberOfTimesCallbackHasRun++;
}, initialValue);
eq(reducedValue, initialValue);
eq(numberOfTimesCallbackHasRun, 0);
},
'If array has one element, and no initialValue, it should return only element.' : function() {
var reducedValue = myReduce([5], function() {});
eq(reducedValue, 5);
}
});
</script>