forked from jashkenas/underscore
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcollections.js
168 lines (131 loc) · 6.76 KB
/
collections.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
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
157
158
159
160
161
162
163
164
165
166
167
168
$(document).ready(function() {
module("Collection functions (each, any, select, and so on...)");
test("collections: each", function() {
_.each([1, 2, 3], function(num, i) {
equals(num, i + 1, 'each iterators provide value and iteration count');
});
var answer = null;
_.each([1, 2, 3], function(num){ if ((answer = num) == 2) _.breakLoop(); });
equals(answer, 2, 'the loop broke in the middle');
var answers = [];
_.each([1, 2, 3], function(num){ answers.push(num * this.multiplier);}, {multiplier : 5});
equals(answers.join(', '), '5, 10, 15', 'context object property accessed');
answers = [];
_.forEach([1, 2, 3], function(num){ answers.push(num); });
equals(answers.join(', '), '1, 2, 3', 'aliased as "forEach"');
answers = [];
var obj = {one : 1, two : 2, three : 3};
obj.constructor.prototype.four = 4;
_.each(obj, function(value, key){ answers.push(key); });
equals(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.');
delete obj.constructor.prototype.four;
answer = null;
_.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; });
ok(answer, 'can reference the original collection from inside the iterator');
answers = [];
_.each({range : 1, speed : 2, length : 3}, function(v){ answers.push(v); });
ok(answers.join(', '), '1, 2, 3', 'can iterate over objects with numeric length properties');
});
test('collections: map', function() {
var doubled = _.map([1, 2, 3], function(num){ return num * 2; });
equals(doubled.join(', '), '2, 4, 6', 'doubled numbers');
var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; }, {multiplier : 3});
equals(tripled.join(', '), '3, 6, 9', 'tripled numbers with context');
var doubled = _([1, 2, 3]).map(function(num){ return num * 2; });
equals(doubled.join(', '), '2, 4, 6', 'OO-style doubled numbers');
var ids = _.map(document.body.childNodes, function(n){ return n.id; });
ok(_.include(ids, 'qunit-header'), 'can use collection methods on NodeLists');
var ids = _.map(document.images, function(n){ return n.id; });
ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections');
});
test('collections: reduce', function() {
var sum = _.reduce([1, 2, 3], 0, function(sum, num){ return sum + num; });
equals(sum, 6, 'can sum up an array');
var context = {multiplier : 3};
sum = _.reduce([1, 2, 3], 0, function(sum, num){ return sum + num * this.multiplier; }, context);
equals(sum, 18, 'can reduce with a context object');
sum = _.inject([1, 2, 3], 0, function(sum, num){ return sum + num; });
equals(sum, 6, 'aliased as "inject"');
sum = _([1, 2, 3]).reduce(0, function(sum, num){ return sum + num; });
equals(sum, 6, 'OO-style reduce');
});
test('collections: reduceRight', function() {
var list = _.foldr([1, 2, 3], '', function(memo, num){ return memo + num; });
equals(list, '321', 'can perform right folds');
});
test('collections: detect', function() {
var result = _.detect([1, 2, 3], function(num){ return num * 2 == 4; });
equals(result, 2, 'found the first "2" and broke the loop');
});
test('collections: select', function() {
var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
equals(evens.join(', '), '2, 4, 6', 'selected each even number');
evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
equals(evens.join(', '), '2, 4, 6', 'aliased as "filter"');
});
test('collections: reject', function() {
var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
equals(odds.join(', '), '1, 3, 5', 'rejected each even number');
});
test('collections: all', function() {
ok(_.all([]), 'the empty set');
ok(_.all([true, true, true]), 'all true values');
ok(!_.all([true, false, true]), 'one false value');
ok(_.all([0, 10, 28], function(num){ return num % 2 == 0; }), 'even numbers');
ok(!_.all([0, 11, 28], function(num){ return num % 2 == 0; }), 'an odd number');
ok(_.every([true, true, true]), 'aliased as "every"');
});
test('collections: any', function() {
ok(!_.any([]), 'the empty set');
ok(!_.any([false, false, false]), 'all false values');
ok(_.any([false, false, true]), 'one true value');
ok(!_.any([1, 11, 29], function(num){ return num % 2 == 0; }), 'all odd numbers');
ok(_.any([1, 10, 29], function(num){ return num % 2 == 0; }), 'an even number');
ok(_.some([false, false, true]), 'aliased as "some"');
});
test('collections: include', function() {
ok(_.include([1,2,3], 2), 'two is in the array');
ok(!_.include([1,3,9], 2), 'two is not in the array');
ok(_.include({moe:1, larry:3, curly:9}, 3), '_.include on objects checks their values');
ok(_([1,2,3]).include(2), 'OO-style include');
});
test('collections: invoke', function() {
var list = [[5, 1, 7], [3, 2, 1]];
var result = _.invoke(list, 'sort');
equals(result[0].join(', '), '1, 5, 7', 'first array sorted');
equals(result[1].join(', '), '1, 2, 3', 'second array sorted');
});
test('collections: pluck', function() {
var people = [{name : 'moe', age : 30}, {name : 'curly', age : 50}];
equals(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects');
});
test('collections: max', function() {
equals(3, _.max([1, 2, 3]), 'can perform a regular Math.max');
var neg = _.max([1, 2, 3], function(num){ return -num; });
equals(neg, 1, 'can perform a computation-based max');
});
test('collections: min', function() {
equals(1, _.min([1, 2, 3]), 'can perform a regular Math.min');
var neg = _.min([1, 2, 3], function(num){ return -num; });
equals(neg, 3, 'can perform a computation-based min');
});
test('collections: sortBy', function() {
var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}];
people = _.sortBy(people, function(person){ return person.age; });
equals(_.pluck(people, 'name').join(', '), 'moe, curly', 'stooges sorted by age');
});
test('collections: sortedIndex', function() {
var numbers = [10, 20, 30, 40, 50], num = 35;
var index = _.sortedIndex(numbers, num);
equals(index, 3, '35 should be inserted at index 3');
});
test('collections: toArray', function() {
ok(!_.isArray(arguments), 'arguments object is not an array');
ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array');
var numbers = _.toArray({one : 1, two : 2, three : 3});
equals(numbers.join(', '), '1, 2, 3', 'object flattened into array');
});
test('collections: size', function() {
equals(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object');
});
});