3 Copyright 2012 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
7 YUI.add('array-extras', function(Y) {
10 Adds additional utility methods to the `Y.Array` class.
13 @submodule array-extras
18 ArrayProto = Array.prototype;
21 Returns the index of the last item in the array that contains the specified
22 value, or `-1` if the value isn't found.
25 @param {Array} a Array to search in.
26 @param {Any} val Value to search for.
27 @param {Number} [fromIndex] Index at which to start searching backwards.
28 Defaults to the array's length - 1. If negative, it will be taken as an offset
29 from the end of the array. If the calculated index is less than 0, the array
30 will not be searched and `-1` will be returned.
31 @return {Number} Index of the item that contains the value, or `-1` if not
36 A.lastIndexOf = L._isNative(ArrayProto.lastIndexOf) ?
37 function(a, val, fromIndex) {
38 // An undefined fromIndex is still considered a value by some (all?)
39 // native implementations, so we can't pass it unless it's actually
41 return fromIndex || fromIndex === 0 ? a.lastIndexOf(val, fromIndex) :
44 function(a, val, fromIndex) {
48 if (fromIndex || fromIndex === 0) {
49 i = Math.min(fromIndex < 0 ? len + fromIndex : fromIndex, len);
52 if (i > -1 && len > 0) {
54 if (i in a && a[i] === val) {
64 Returns a copy of the specified array with duplicate items removed.
67 @param {Array} a Array to dedupe.
68 @return {Array} Copy of the array with duplicate items removed.
71 A.unique = function(a, sort) {
72 // Note: the sort param is deprecated and intentionally undocumented since
73 // YUI 3.3.0. It never did what the API docs said it did (see the older
74 // comment below as well).
80 for (; i < len; ++i) {
83 // This loop iterates over the results array in reverse order and stops
84 // if it finds an item that matches the current input array item (a
85 // dupe). If it makes it all the way through without finding a dupe, the
86 // current item is pushed onto the results array.
87 for (j = results.length; j > -1; --j) {
88 if (item === results[j]) {
98 // Note: the sort option doesn't really belong here... I think it was added
99 // because there was a way to fast path the two operations together. That
100 // implementation was not working, so I replaced it with the following.
101 // Leaving it in so that the API doesn't get broken.
104 if (L.isNumber(results[0])) {
105 results.sort(A.numericSort);
115 Executes the supplied function on each item in the array. Returns a new array
116 containing the items for which the supplied function returned a truthy value.
119 @param {Array} a Array to filter.
120 @param {Function} f Function to execute on each item.
121 @param {Object} [o] Optional context object.
122 @return {Array} Array of items for which the supplied function returned a
123 truthy value (empty if it never returned a truthy value).
126 A.filter = L._isNative(ArrayProto.filter) ?
128 return a.filter(f, o);
136 for (; i < len; ++i) {
140 if (f.call(o, item, i, a)) {
150 The inverse of `Array.filter()`. Executes the supplied function on each item.
151 Returns a new array containing the items for which the supplied function
155 @param {Array} a the array to iterate.
156 @param {Function} f the function to execute on each item.
157 @param {object} [o] Optional context object.
158 @return {Array} The items for which the supplied function returned `false`.
161 A.reject = function(a, f, o) {
162 return A.filter(a, function(item, i, a) {
163 return !f.call(o, item, i, a);
168 Executes the supplied function on each item in the array. Iteration stops if the
169 supplied function does not return a truthy value.
172 @param {Array} a the array to iterate.
173 @param {Function} f the function to execute on each item.
174 @param {Object} [o] Optional context object.
175 @return {Boolean} `true` if every item in the array returns `true` from the
176 supplied function, `false` otherwise.
179 A.every = L._isNative(ArrayProto.every) ?
181 return a.every(f, o);
184 for (var i = 0, l = a.length; i < l; ++i) {
185 if (i in a && !f.call(o, a[i], i, a)) {
194 Executes the supplied function on each item in the array and returns a new array
195 containing all the values returned by the supplied function.
199 // Convert an array of numbers into an array of strings.
200 Y.Array.map([1, 2, 3, 4], function (item) {
203 // => ['1', '2', '3', '4']
206 @param {Array} a the array to iterate.
207 @param {Function} f the function to execute on each item.
208 @param {object} [o] Optional context object.
209 @return {Array} A new array containing the return value of the supplied function
210 for each item in the original array.
213 A.map = L._isNative(ArrayProto.map) ?
220 results = a.concat();
222 for (; i < len; ++i) {
224 results[i] = f.call(o, a[i], i, a);
233 Executes the supplied function on each item in the array, "folding" the array
237 @param {Array} a Array to iterate.
238 @param {Any} init Initial value to start with.
239 @param {Function} f Function to execute on each item. This function should
240 update and return the value of the computation. It will receive the following
242 @param {Any} f.previousValue Value returned from the previous iteration,
243 or the initial value if this is the first iteration.
244 @param {Any} f.currentValue Value of the current item being iterated.
245 @param {Number} f.index Index of the current item.
246 @param {Array} f.array Array being iterated.
247 @param {Object} [o] Optional context object.
248 @return {Any} Final result from iteratively applying the given function to each
249 element in the array.
252 A.reduce = L._isNative(ArrayProto.reduce) ?
253 function(a, init, f, o) {
254 // ES5 Array.reduce doesn't support a thisObject, so we need to
255 // implement it manually.
256 return a.reduce(function(init, item, i, a) {
257 return f.call(o, init, item, i, a);
260 function(a, init, f, o) {
265 for (; i < len; ++i) {
267 result = f.call(o, result, a[i], i, a);
275 Executes the supplied function on each item in the array, searching for the
276 first item that matches the supplied function.
279 @param {Array} a the array to search.
280 @param {Function} f the function to execute on each item. Iteration is stopped
281 as soon as this function returns `true`.
282 @param {Object} [o] Optional context object.
283 @return {Object} the first item that the supplied function returns `true` for,
284 or `null` if it never returns `true`.
287 A.find = function(a, f, o) {
288 for (var i = 0, l = a.length; i < l; i++) {
289 if (i in a && f.call(o, a[i], i, a)) {
297 Iterates over an array, returning a new array of all the elements that match the
298 supplied regular expression.
301 @param {Array} a Array to iterate over.
302 @param {RegExp} pattern Regular expression to test against each item.
303 @return {Array} All the items in the array that produce a match against the
304 supplied regular expression. If no items match, an empty array is returned.
307 A.grep = function(a, pattern) {
308 return A.filter(a, function(item, index) {
309 return pattern.test(item);
314 Partitions an array into two new arrays, one with the items for which the
315 supplied function returns `true`, and one with the items for which the function
319 @param {Array} a Array to iterate over.
320 @param {Function} f Function to execute for each item in the array. It will
321 receive the following arguments:
322 @param {Any} f.item Current item.
323 @param {Number} f.index Index of the current item.
324 @param {Array} f.array The array being iterated.
325 @param {Object} [o] Optional execution context.
326 @return {Object} An object with two properties: `matches` and `rejects`. Each is
327 an array containing the items that were selected or rejected by the test
328 function (or an empty array if none).
331 A.partition = function(a, f, o) {
337 A.each(a, function(item, index) {
338 var set = f.call(o, item, index, a) ? results.matches : results.rejects;
346 Creates an array of arrays by pairing the corresponding elements of two arrays
347 together into a new array.
350 @param {Array} a Array to iterate over.
351 @param {Array} a2 Another array whose values will be paired with values of the
353 @return {Array} An array of arrays formed by pairing each element of the first
354 array with an item in the second array having the corresponding index.
357 A.zip = function(a, a2) {
359 A.each(a, function(item, index) {
360 results.push([item, a2[index]]);
366 }, '3.5.1' ,{requires:['yui-base']});