|
1 /* |
|
2 Copyright (c) 2009, Yahoo! Inc. All rights reserved. |
|
3 Code licensed under the BSD License: |
|
4 http://developer.yahoo.net/yui/license.txt |
|
5 version: 3.0.0b1 |
|
6 build: 1163 |
|
7 */ |
|
8 YUI.add('collection', function(Y) { |
|
9 |
|
10 /** |
|
11 * Collection utilities beyond what is provided in the YUI core |
|
12 * @module collection |
|
13 */ |
|
14 |
|
15 var L = Y.Lang, Native = Array.prototype, A = Y.Array; |
|
16 |
|
17 /** |
|
18 * Adds the following array utilities to the YUI instance |
|
19 * (Y.Array). This is in addition to the methods provided |
|
20 * in the core. |
|
21 * @class YUI~array~extras |
|
22 */ |
|
23 |
|
24 /** |
|
25 * Returns the index of the last item in the array |
|
26 * that contains the specified value, -1 if the |
|
27 * value isn't found. |
|
28 * method Array.lastIndexOf |
|
29 * @static |
|
30 * @param a {Array} the array to search |
|
31 * @param val the value to search for |
|
32 * @return {int} the index of hte item that contains the value or -1 |
|
33 */ |
|
34 A.lastIndexOf = (Native.lastIndexOf) ? |
|
35 function(a ,val) { |
|
36 return a.lastIndexOf(val); |
|
37 } : |
|
38 function(a, val) { |
|
39 for (var i=a.length-1; i>=0; i=i-1) { |
|
40 if (a[i] === val) { |
|
41 break; |
|
42 } |
|
43 } |
|
44 return i; |
|
45 }; |
|
46 |
|
47 /** |
|
48 * Returns a copy of the array with the duplicate entries removed |
|
49 * @method Array.unique |
|
50 * @static |
|
51 * @param a {Array} the array to find the subset of uniques for |
|
52 * @param sort {bool} flag to denote if the array is sorted or not. Defaults to false, the more general operation |
|
53 * @return {Array} a copy of the array with duplicate entries removed |
|
54 */ |
|
55 A.unique = function(a, sort) { |
|
56 var s = L.isValue(sort) ? sort : false, |
|
57 b = a.slice(), i = 0, n = -1, item = null; |
|
58 if (s) { |
|
59 while (i < b.length) { |
|
60 if (b[i] === item) { |
|
61 n = (n == -1 ? i : n); |
|
62 i += 1; |
|
63 } else if (n !== -1) { |
|
64 b.splice(n, i-n); |
|
65 i = n; |
|
66 n = -1; |
|
67 } else { |
|
68 item = b[i]; |
|
69 i += 1; |
|
70 } |
|
71 } |
|
72 return b; |
|
73 } else { |
|
74 while (i < b.length) { |
|
75 item = b[i]; |
|
76 while ((n = b.lastIndexOf(item)) !== i) { |
|
77 b.splice(n, 1); |
|
78 } |
|
79 i += 1; |
|
80 } |
|
81 return b; |
|
82 } |
|
83 }; |
|
84 |
|
85 /** |
|
86 * Executes the supplied function on each item in the array. |
|
87 * Returns a new array containing the items that the supplied |
|
88 * function returned true for. |
|
89 * @method Array.filter |
|
90 * @param a {Array} the array to iterate |
|
91 * @param f {Function} the function to execute on each item |
|
92 * @param o Optional context object |
|
93 * @static |
|
94 * @return {Array} The items on which the supplied function |
|
95 * returned true. If no items matched an empty array is |
|
96 * returned. |
|
97 */ |
|
98 A.filter = (Native.filter) ? |
|
99 function(a, f, o) { |
|
100 return Native.filter.call(a, f, o); |
|
101 } : |
|
102 function(a, f, o) { |
|
103 var results = []; |
|
104 A.each(a, function(item, i, a) { |
|
105 if (f.call(o, item, i, a)) { |
|
106 results.push(item); |
|
107 } |
|
108 }); |
|
109 |
|
110 return results; |
|
111 }; |
|
112 |
|
113 /** |
|
114 * The inverse of filter. Executes the supplied function on each item. |
|
115 * Returns a new array containing the items that the supplied |
|
116 * function returned *false* for. |
|
117 * @method Array.reject |
|
118 * @param a {Array} the array to iterate |
|
119 * @param f {Function} the function to execute on each item |
|
120 * @param o Optional context object |
|
121 * @static |
|
122 * @return {Array} The items on which the supplied function |
|
123 * returned false. |
|
124 */ |
|
125 A.reject = function(a, f, o) { |
|
126 return A.filter(a, function(item, i, a) { |
|
127 return !f.call(o, item, i, a); |
|
128 }); |
|
129 }; |
|
130 |
|
131 /** |
|
132 * Executes the supplied function on each item in the array. |
|
133 * @method Array.every |
|
134 * @param a {Array} the array to iterate |
|
135 * @param f {Function} the function to execute on each item |
|
136 * @param o Optional context object |
|
137 * @static |
|
138 * @return {boolean} true if every item in the array returns true |
|
139 * from the supplied function. |
|
140 */ |
|
141 A.every = (Native.every) ? |
|
142 function(a, f, o) { |
|
143 return Native.every.call(a,f,o); |
|
144 } : |
|
145 function(a, f, o) { |
|
146 var l = a.length; |
|
147 for (var i = 0; i < l; i=i+1) { |
|
148 if (!f.call(o, a[i], i, a)) { |
|
149 return false; |
|
150 } |
|
151 } |
|
152 |
|
153 return true; |
|
154 }; |
|
155 |
|
156 /** |
|
157 * Executes the supplied function on each item in the array. |
|
158 * @method Array.map |
|
159 * @param a {Array} the array to iterate |
|
160 * @param f {Function} the function to execute on each item |
|
161 * @param o Optional context object |
|
162 * @static |
|
163 * @return {Array} A new array containing the return value |
|
164 * of the supplied function for each item in the original |
|
165 * array. |
|
166 */ |
|
167 A.map = (Native.map) ? |
|
168 function(a, f, o) { |
|
169 return Native.map.call(a, f, o); |
|
170 } : |
|
171 function(a, f, o) { |
|
172 var results = []; |
|
173 A.each(a, function(item, i, a) { |
|
174 results.push(f.call(o, item, i, a)); |
|
175 }); |
|
176 return results; |
|
177 }; |
|
178 |
|
179 |
|
180 /** |
|
181 * Executes the supplied function on each item in the array. |
|
182 * Reduce "folds" the array into a single value. |
|
183 * @method Array.reduce |
|
184 * @param a {Array} the array to iterate |
|
185 * @param init The initial value to start from |
|
186 * @param f {Function} the function to execute on each item. It |
|
187 * is responsible for returning the updated value of the |
|
188 * computation. |
|
189 * @param o Optional context object |
|
190 * @static |
|
191 * @return A value that results from iteratively applying the |
|
192 * supplied function to each element in the array. |
|
193 */ |
|
194 A.reduce = (Native.reduce) ? |
|
195 function(a, init, f, o) { |
|
196 //Firefox's Array.reduce does not allow inclusion of a |
|
197 // thisObject, so we need to implement it manually |
|
198 return Native.reduce.call(a, function(init, item, i, a) { |
|
199 return f.call(o, init, item, i, a); |
|
200 }, init); |
|
201 } : |
|
202 function(a, init, f, o) { |
|
203 var r = init; |
|
204 A.each(a, function (item, i, a) { |
|
205 r = f.call(o, r, item, i, a); |
|
206 }); |
|
207 return r; |
|
208 }; |
|
209 |
|
210 |
|
211 /** |
|
212 * Executes the supplied function on each item in the array, |
|
213 * searching for the first item that matches the supplied |
|
214 * function. |
|
215 * @method Array.find |
|
216 * @param a {Array} the array to search |
|
217 * @param f {Function} the function to execute on each item. |
|
218 * Iteration is stopped as soon as this function returns true |
|
219 * on an item. |
|
220 * @param o Optional context object |
|
221 * @static |
|
222 * @return {object} the first item that the supplied function |
|
223 * returns true for, or null if it never returns true |
|
224 */ |
|
225 A.find = function(a, f, o) { |
|
226 var l = a.length; |
|
227 for(var i=0; i < l; i++) { |
|
228 if (f.call(o, a[i], i, a)) { |
|
229 return a[i]; |
|
230 } |
|
231 } |
|
232 return null; |
|
233 }; |
|
234 |
|
235 /** |
|
236 * Iterates over an array, returning a new array of all the elements |
|
237 * that match the supplied regular expression |
|
238 * @method Array.grep |
|
239 * @param a {Array} a collection to iterate over |
|
240 * @param pattern {RegExp} The regular expression to test against |
|
241 * each item |
|
242 * @static |
|
243 * @return {Array} All the items in the collection that |
|
244 * produce a match against the supplied regular expression. |
|
245 * If no items match, an empty array is returned. |
|
246 */ |
|
247 A.grep = function (a, pattern) { |
|
248 return A.filter(a, function (item, index) { |
|
249 return pattern.test(item); |
|
250 }); |
|
251 }; |
|
252 |
|
253 |
|
254 /** |
|
255 * Partitions an array into two new arrays, one with the items |
|
256 * that match the supplied function, and one with the items that |
|
257 * do not. |
|
258 * @method Array.partition |
|
259 * @param a {Array} a collection to iterate over |
|
260 * @paran f {Function} a function that will receive each item |
|
261 * in the collection and its index. |
|
262 * @param o Optional execution context of f. |
|
263 * @static |
|
264 * @return An object with two members, 'matches' and 'rejects', |
|
265 * that are arrays containing the items that were selected or |
|
266 * rejected by the test function (or an empty array). |
|
267 */ |
|
268 A.partition = function (a, f, o) { |
|
269 var results = {matches: [], rejects: []}; |
|
270 A.each(a, function (item, index) { |
|
271 var set = f.call(o, item, index, a) ? results.matches : results.rejects; |
|
272 set.push(item); |
|
273 }); |
|
274 return results; |
|
275 }; |
|
276 |
|
277 /** |
|
278 * Creates an array of arrays by pairing the corresponding |
|
279 * elements of two arrays together into a new array. |
|
280 * @method Array.zip |
|
281 * @param a {Array} a collection to iterate over |
|
282 * @param a2 {Array} another collection whose members will be |
|
283 * paired with members of the first parameter |
|
284 * @static |
|
285 * @return An array of arrays formed by pairing each element |
|
286 * of the first collection with an item in the second collection |
|
287 * having the corresponding index. |
|
288 */ |
|
289 A.zip = function (a, a2) { |
|
290 var results = []; |
|
291 A.each(a, function (item, index) { |
|
292 results.push([item, a2[index]]); |
|
293 }); |
|
294 return results; |
|
295 }; |
|
296 |
|
297 |
|
298 }, '3.0.0b1' ); |