In prototype the cumbersome for:
for (i=0; i<10; i++) { ... }
can be written as
$R(0, 10).each(function(i){ ... });
Is there an equivalent of range in JQuery ?
In prototype the cumbersome for:
for (i=0; i<10; i++) { ... }
can be written as
$R(0, 10).each(function(i){ ... });
Is there an equivalent of range in JQuery ?
Share Improve this question edited Dec 28, 2011 at 22:29 Rob W 349k87 gold badges807 silver badges682 bronze badges asked May 18, 2010 at 8:50 clyfeclyfe 23.8k8 gold badges88 silver badges110 bronze badges 4- 5 Interesting how the "cumbersome" first example is fewer characters than the second example. It will also run faster. – Tim Down Commented May 18, 2010 at 10:15
-
1
Admittedly, the first example does have the downside of putting the loop variable
i
in the current scope (or the global scope if there's novar i
elsewhere in this scope). – Tim Down Commented May 18, 2010 at 15:57 -
Maybe not in the above example, since it's dealing with numbers specifically which are not indexes, but when iterating over a collection, all those i's in
var i = 0; i < x.length; i++)
and object access asx[i]
are pure hassle when all that's needed is going over each object in a collection and doing something with it (nothing to do with indexes). Collection iteration and manipulation methods such asmap, filter, any, all, each, reduce, ..
should be part of each language and I am glad the ES5 spec includes these. – Anurag Commented May 19, 2010 at 2:24 - 1 Is easier for my brain to think in terms of range-iteration instead of condition-loop-increment I guess, anyway, a range thingy is good to have. – clyfe Commented Jun 2, 2010 at 12:11
2 Answers
Reset to default 4See http://code.google./p/jquery-utils/source/browse/trunk/src/jquery.arrayUtils.js?r=452
jQuery does not provide range expansion natively, but it's an easy addition. There are only two parts to it. First the range function should return an array with the each item in the range expanded to an array value. Next add a method to Array
to iterate each object passing in a handler function.
Here we define forEach
that's part of the ECMA-262 standard for iterating over arrays. See MDC for more details.
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(fun /*, thisp*/) {
var len = this.length >>> 0;
if (typeof fun != "function")
throw new TypeError();
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this)
fun.call(thisp, this[i], i, this);
}
};
}
Next, we need a function to expand ranges to an array within the jQuery namespace. Taken from the above URL (original source - http://blog.outofhanwell./2006/03/29/javascript-range-function/) :
$.extend({
// Returns a range object
// Author: Matthias Miller
// Site: http://blog.outofhanwell./2006/03/29/javascript-range-function/
range: function() {
if (!arguments.length) { return []; }
var min, max, step;
if (arguments.length == 1) {
min = 0;
max = arguments[0]-1;
step = 1;
}
else {
// default step to 1 if it's zero or undefined
min = arguments[0];
max = arguments[1]-1;
step = arguments[2] || 1;
}
// convert negative steps to positive and reverse min/max
if (step < 0 && min >= max) {
step *= -1;
var tmp = min;
min = max;
max = tmp;
min += ((max-min) % step);
}
var a = [];
for (var i = min; i <= max; i += step) { a.push(i); }
return a;
}
});
Alrighty, now we can do:
$.range(2, 10).forEach(function(v) {
console.log(v); // 2, 3, 4, .., 9
});
Or use it with a custom step value instead of 1
$.range(2, 20, 4).forEach(function(v) {
console.log(v); // 2, 6, 10, 14, 18
});
I'd prefer a generator to an array - more elegant (imho) and more memory efficient.
function Range(low, high){
this.low = low;
this.high = high;
}
Range.prototype.__iterator__ = function(){
for (var i = this.low; i <= this.high; i++)
yield i;
};
Then you can simply
var range = new Range(3, 5);
for (var i in range)
print(i); // prints 3, then 4, then 5 in sequence
From: https://developer.mozilla/en/Core_JavaScript_1.5_Guide/Iterators_and_Generators