I read some code where someone did this in Ruby:
puts ('A'..'Z').to_a.join(',')
output:
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
Is there something in Javascript
that will allow this to be done just as easy? if not, is there Node module that allows for something similar?
Javascript doesn't have that functionality natively. Below you find some examples of how it could be solved:
Normal function, any characters from the base plane (no checking for surrogate pairs)
function range(start,stop) {
var result=[];
for (var idx=start.charCodeAt(0),end=stop.charCodeAt(0); idx <=end; ++idx){
result.push(String.fromCharCode(idx));
}
return result;
};
range('A','Z').join();
The same as above, but as a function added to the array prototype, and therefore available to all arrays:
Array.prototype.add_range = function(start,stop) {
for (var idx=start.charCodeAt(0),end=stop.charCodeAt(0); idx <=end; ++idx){
this.push(String.fromCharCode(idx));
}
return this;
};
[].add_range('A','Z').join();
A range from preselected characters. Is faster than the functions above, and let you use alphanum_range('A','z')
to mean A-Z and a-z:
var alphanum_range = (function() {
var data = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split('');
return function (start,stop) {
start = data.indexOf(start);
stop = data.indexOf(stop);
return (!~start || !~stop) ? null : data.slice(start,stop+1);
};
})();
alphanum_range('A','Z').join();
Or any character from the ascii range. By using a cached array, it is faster than the functions that build the array every time.
var ascii_range = (function() {
var data = [];
while (data.length < 128) data.push(String.fromCharCode(data.length));
return function (start,stop) {
start = start.charCodeAt(0);
stop = stop.charCodeAt(0);
return (start < 0 || start > 127 || stop < 0 || stop > 127) ? null : data.slice(start,stop+1);
};
})();
ascii_range('A','Z').join();
Take a look at the answer from kannebec for a similar question.
Does JavaScript have a range() equivalent?
If you don't want to add a own function, but in one line:
var abc =
(function(){var output = []; for(var i='A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++)
output.push(String.fromCharCode(i)); return output;})().join(',');
var chars = [].concat.apply([], Array(26))
.map(function(_, i) { return String.fromCharCode(i+65); })
.join();
The .map
function could be a function generator that could be used for different character sets.
function charRange(start) {
var base = start.charCodeAt(0);
return function(_, i) { return String.fromCharCode(i + base); };
}
And you may also want to create a "full" Array helper.
function fullArray(len) { return [].concat.apply([], Array(len)); }
Then use them like this.
var chars = fullArray(26).map(charRange("A"))
.join();
CoffeeScript compiles to javascript, and it has numeric ranges:
(String.fromCharCode(x+64) for x in [1..26]).join(",")
Here's a link to this script in the coffeescript.org site. You can see what javascript it compiles to, and run it in your browser live.
(And yes, you can use coffeescript for Node.js)
TL;DR
// ['a', .. , 'z']
Array.apply(null, {length: 26})
.map(function (x,i) { return String.fromCharCode(97 + i) });
Or even
function range(first, last) {
var a = first.charCodeAt(0)
var b = last.charCodeAt(0) + 1
return Array.apply(null, {length: Math.abs(b - a)})
.map(function (x,i) { return String.fromCharCode(Math.min(a, b) + i) });
}
range('K','M') // => ['K','L','M']
range('$','z') // => "$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz"
I think this can be expressed clearest in a functional way: map [0 .. 25]
to ['a' .. 'z']
.
We can use fromCharCode(n)
to convert a number into a string. To find the numerical value corresponding to a character we need it's inverse function, toCharCode(s)
:
var toCharCode = function(s){ return s.charCodeAt(0) } // 'a' => 97, 'b' => 98, ..
Then the rest is easy:
Array.apply(null, {length: 26})
.map(function (x,i) { return String.fromCharCode(97 + i) });
Constructs an array of 26 undefined's: [undefined, ... , undefined]
. Then map
index i
of each value to 97 + i
== 'a'.charCodeAt(0) + i
(for uppercase start at 'A' => 65
).
This first line might need some explanation. What we are effectively doing is the same as Array(1,2,3)
== [1,2,3]
. Instead of passing an actual array to apply
, we pass something that quacks like an array (has the length
property). This results in calling Array(undefined, .. , undefined)
.
See
apply
and
"generic array-like object"
for more infomation.
Maybe this function will help you.
function range ( low, high, step ) { // Create an array containing a range of elements
//
// + original by: _argos
var matrix = [];
var inival, endval, plus;
var walker = step || 1;
var chars = false;
if ( !isNaN ( low ) && !isNaN ( high ) ) {
inival = low;
endval = high;
} else if ( isNaN ( low ) && isNaN ( high ) ) {
chars = true;
inival = low.charCodeAt ( 0 );
endval = high.charCodeAt ( 0 );
} else {
inival = ( isNaN ( low ) ? 0 : low );
endval = ( isNaN ( high ) ? 0 : high );
}
plus = ( ( inival > endval ) ? false : true );
if ( plus ) {
while ( inival <= endval ) {
matrix.push ( ( ( chars ) ? String.fromCharCode ( inival ) : inival ) );
inival += walker;
}
} else {
while ( inival >= endval ) {
matrix.push ( ( ( chars ) ? String.fromCharCode ( inival ) : inival ) );
inival -= walker;
}
}
return matrix;
}
console.log(range('A','Z'))
// ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
This is not mine, taken from: http://javascript.ru/php/range
No, JavaScript does not have any built-in Range object. You would need to write a function to create an abstract Range, and then add a to_a
method for the equivalence.
For fun, here's an alternative way to get that exact output, with no intermediary strings.
function commaRange(startChar,endChar){
var c=','.charCodeAt(0);
for (var a=[],i=startChar.charCodeAt(0),e=endChar.charCodeAt(0);i<=e;++i){
a.push(i); a.push(c);
}
a.pop();
return String.fromCharCode.apply(String,a);
}
console.log(commaRange('A','J')); // "A,B,C,D,E,F,G,H,I,J"
For Node.js, there is the Lazy module.
function range(r, x) {
var c1 = r.charCodeAt(0)+1, c2 = r.charCodeAt(3), s = r[0];
if(c1 && c2)while (c1 <= c2) s += (x || "") + String.fromCharCode(c1++);
return s;
}
range("A--S", ",");
var range = [];
for(var i = 65; i < 91; i++)
{
range.push(String.fromCharCode(i));
}
range = range.join(',');
gives range a-z, but i like the function option of some too.