JavaScript是否有像“range()”这样的方法来在提供的边界内生成范围?

在PHP中,您可以…

range(1, 3); // Array(1, 2, 3)range("A", "C"); // Array("A", "B", "C")

也就是说,有一个函数可以让您通过传递上限和下限来获取一系列数字或字符。

JavaScript本身有什么内置的东西吗?如果没有,我将如何实现它?

1306479 次浏览

标准Javascript没有生成范围的内置函数。几个javascript框架添加了对此类功能的支持,或者正如其他人指出的那样,您可以随时推出自己的功能。

如果您想仔细检查,最终资源是ECMA-262标准

它适用于字符和数字,向前或向后进行可选步骤。

var range = function(start, end, step) {var range = [];var typeofStart = typeof start;var typeofEnd = typeof end;
if (step === 0) {throw TypeError("Step cannot be zero.");}
if (typeofStart == "undefined" || typeofEnd == "undefined") {throw TypeError("Must pass start and end arguments.");} else if (typeofStart != typeofEnd) {throw TypeError("Start and end arguments must be of same type.");}
typeof step == "undefined" && (step = 1);
if (end < start) {step = -step;}
if (typeofStart == "number") {
while (step > 0 ? end >= start : end <= start) {range.push(start);start += step;}
} else if (typeofStart == "string") {
if (start.length != 1 || end.length != 1) {throw TypeError("Only strings with one character are supported.");}
start = start.charCodeAt(0);end = end.charCodeAt(0);
while (step > 0 ? end >= start : end <= start) {range.push(String.fromCharCode(start));start += step;}
} else {throw TypeError("Only string and number types are supported");}
return range;
}

jsFiddle

如果增加本机类型是你的事情,那么将其分配给Array.range

var range = function(start, end, step) {var range = [];var typeofStart = typeof start;var typeofEnd = typeof end;
if (step === 0) {throw TypeError("Step cannot be zero.");}
if (typeofStart == "undefined" || typeofEnd == "undefined") {throw TypeError("Must pass start and end arguments.");} else if (typeofStart != typeofEnd) {throw TypeError("Start and end arguments must be of same type.");}
typeof step == "undefined" && (step = 1);
if (end < start) {step = -step;}
if (typeofStart == "number") {
while (step > 0 ? end >= start : end <= start) {range.push(start);start += step;}
} else if (typeofStart == "string") {
if (start.length != 1 || end.length != 1) {throw TypeError("Only strings with one character are supported.");}
start = start.charCodeAt(0);end = end.charCodeAt(0);
while (step > 0 ? end >= start : end <= start) {range.push(String.fromCharCode(start));start += step;}
} else {throw TypeError("Only string and number types are supported");}
return range;
}
console.log(range("A", "Z", 1));console.log(range("Z", "A", 1));console.log(range("A", "Z", 3));

console.log(range(0, 25, 1));
console.log(range(0, 25, 5));console.log(range(20, 5, 5));

Array.range = function(a, b, step){var A = [];if(typeof a == 'number'){A[0] = a;step = step || 1;while(a+step <= b){A[A.length]= a+= step;}}else {var s = 'abcdefghijklmnopqrstuvwxyz';if(a === a.toUpperCase()){b = b.toUpperCase();s = s.toUpperCase();}s = s.substring(s.indexOf(a), s.indexOf(b)+ 1);A = s.split('');}return A;}    
    
Array.range(0,10);// [0,1,2,3,4,5,6,7,8,9,10]    
Array.range(-100,100,20);// [-100,-80,-60,-40,-20,0,20,40,60,80,100]    
Array.range('A','F');// ['A','B','C','D','E','F')    
Array.range('m','r');// ['m','n','o','p','q','r']

数字

[...Array(5).keys()];=> [0, 1, 2, 3, 4]

角色迭代

String.fromCharCode(...[...Array('D'.charCodeAt(0) - 'A'.charCodeAt(0) + 1).keys()].map(i => i + 'A'.charCodeAt(0)));=> "ABCD"

迭代:

for (const x of Array(5).keys()) {console.log(x, String.fromCharCode('A'.charCodeAt(0) + x));}=> 0,"A" 1,"B" 2,"C" 3,"D" 4,"E"

作为职能

function range(size, startAt = 0) {return [...Array(size).keys()].map(i => i + startAt);}
function characterRange(startChar, endChar) {return String.fromCharCode(...range(endChar.charCodeAt(0) -startChar.charCodeAt(0), startChar.charCodeAt(0)))}

作为类型化函数

function range(size:number, startAt:number = 0):ReadonlyArray<number> {return [...Array(size).keys()].map(i => i + startAt);}
function characterRange(startChar:string, endChar:string):ReadonlyArray<string> {return String.fromCharCode(...range(endChar.charCodeAt(0) -startChar.charCodeAt(0), startChar.charCodeAt(0)))}

lodash.js#0功能

_.range(10);=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]_.range(1, 11);=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]_.range(0, 30, 5);=> [0, 5, 10, 15, 20, 25]_.range(0, -10, -1);=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]String.fromCharCode(..._.range('A'.charCodeAt(0), 'D'.charCodeAt(0) + 1));=> "ABCD"

没有库的旧非es6浏览器:

Array.apply(null, Array(5)).map(function (_, i) {return i;});=> [0, 1, 2, 3, 4]

console.log([...Array(5).keys()]);

(ES6 credit to nils petersohn and other commenters)

使用和声发生器支持除IE11以外的所有浏览器

var take = function (amount, generator) {var a = [];
try {while (amount) {a.push(generator.next());amount -= 1;}} catch (e) {}
return a;};
var takeAll = function (gen) {var a = [],x;
try {do {x = a.push(gen.next());} while (x);} catch (e) {}
return a;};
var range = (function (d) {var unlimited = (typeof d.to === "undefined");
if (typeof d.from === "undefined") {d.from = 0;}
if (typeof d.step === "undefined") {if (unlimited) {d.step = 1;}} else {if (typeof d.from !== "string") {if (d.from < d.to) {d.step = 1;} else {d.step = -1;}} else {if (d.from.charCodeAt(0) < d.to.charCodeAt(0)) {d.step = 1;} else {d.step = -1;}}}
if (typeof d.from === "string") {for (let i = d.from.charCodeAt(0); (d.step > 0) ? (unlimited ? true : i <= d.to.charCodeAt(0)) : (i >= d.to.charCodeAt(0)); i += d.step) {yield String.fromCharCode(i);}} else {for (let i = d.from; (d.step > 0) ? (unlimited ? true : i <= d.to) : (i >= d.to); i += d.step) {yield i;}}});

示例

采取

例1。

take只需要尽可能多的东西

take(10, range( {from: 100, step: 5, to: 120} ) )

返回

[100, 105, 110, 115, 120]

例2。

to不需要

take(10, range( {from: 100, step: 5} ) )

返回

[100, 105, 110, 115, 120, 125, 130, 135, 140, 145]

全盘

例3。

from不需要

takeAll( range( {to: 5} ) )

返回

[0, 1, 2, 3, 4, 5]

例4。

takeAll( range( {to: 500, step: 100} ) )

返回

[0, 100, 200, 300, 400, 500]

例5。

takeAll( range( {from: 'z', to: 'a'} ) )

返回

["z", "y", "x", "w", "v", "u", "t", "s", "r", "q", "p", "o", "n", "m", "l", "k", "j", "i", "h", "g", "f", "e", "d", "c", "b", "a"]

简单的范围功能:

function range(start, stop, step) {var a = [start], b = start;while (b < stop) {a.push(b += step || 1);}return a;}

要合并BigInt数据类型,可以包含一些检查,确保所有变量都相同typeof start

function range(start, stop, step) {var a = [start], b = start;if (typeof start == 'bigint') {stop = BigInt(stop)step = step? BigInt(step): 1n;} elsestep = step || 1;while (b < stop) {a.push(b += step);}return a;}

要删除高于stop定义的值,例如range(0,5,2)将包含6,这不应该。

function range(start, stop, step) {var a = [start], b = start;while (b < stop) {a.push(b += step || 1);}return (b > stop) ? a.slice(0,-1) : a;}

这是我的2美分:

function range(start, end) {return Array.apply(0, Array(end - 1)).map((element, index) => index + start);}

对一些不同的范围函数进行了一些研究。检查jspef比较实现这些功能的不同方法。当然不是一个完美或详尽的列表,但应该有帮助:)

胜利者是…

function range(lowEnd,highEnd){var arr = [],c = highEnd - lowEnd + 1;while ( c-- ) {arr[c] = highEnd--}return arr;}range(0,31);

从技术上讲,它不是Firefox上最快的,但chrome上疯狂的速度差异(imho)弥补了它。

同样有趣的观察是chrome使用这些数组函数比Firefox快多少。Chrome至少快四五倍

我发现了一个相当于PHP中的JS范围函数,并且工作得非常好这里。向前和向后工作,并使用整数、浮点数和字母!

function range(low, high, step) {//  discuss at: http://phpjs.org/functions/range/// original by: Waldo Malqui Silva//   example 1: range ( 0, 12 );//   returns 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]//   example 2: range( 0, 100, 10 );//   returns 2: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]//   example 3: range( 'a', 'i' );//   returns 3: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']//   example 4: range( 'c', 'a' );//   returns 4: ['c', 'b', 'a']
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;}

以下是缩小版:

function range(h,c,b){var i=[];var d,f,e;var a=b||1;var g=false;if(!isNaN(h)&&!isNaN(c)){d=h;f=c}else{if(isNaN(h)&&isNaN(c)){g=true;d=h.charCodeAt(0);f=c.charCodeAt(0)}else{d=(isNaN(h)?0:h);f=(isNaN(c)?0:c)}}e=((d>f)?false:true);if(e){while(d<=f){i.push(((g)?String.fromCharCode(d):d));d+=a}}else{while(d>=f){i.push(((g)?String.fromCharCode(d):d));d-=a}}return i};

虽然这不是来自php,但从Python模仿range

function range(start, end) {var total = [];
if (!end) {end = start;start = 0;}
for (var i = start; i < end; i += 1) {total.push(i);}
return total;}
console.log(range(10)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]console.log(range(0, 10)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]console.log(range(5, 10)); // [5, 6, 7, 8, 9]

对于具有良好向后兼容性的更类似ruby的方法:

range([begin], end = 0)其中beginend是数字

var range = function(begin, end) {if (typeof end === "undefined") {end = begin; begin = 0;}var result = [], modifier = end > begin ? 1 : -1;for ( var i = 0; i <= Math.abs(end - begin); i++ ) {result.push(begin + i * modifier);}return result;}

示例:

range(3); //=> [0, 1, 2, 3]range(-2); //=> [0, -1, -2]range(1, 2) //=> [1, 2]range(1, -2); //=> [1, 0, -1, -2]

一个有趣的挑战是编写最短函数来执行此操作。递归救援!

function r(a,b){return a>b?[]:[a].concat(r(++a,b))}

在大范围内往往很慢,但幸运的是量子计算机就在眼前。

额外的好处是它是模糊的。因为我们都知道隐藏我们的代码免受窥探是多么重要。

要真正完全混淆函数,请执行以下操作:

function r(a,b){return (a<b?[a,b].concat(r(++a,--b)):a>b?[]:[a]).sort(function(a,b){return a-b})}

使用Harmony点差算子和箭头函数:

var range = (start, end) => [...Array(end - start + 1)].map((_, i) => start + i);

示例:

range(10, 15);[ 10, 11, 12, 13, 14, 15 ]

您可以使用lodash函数_.range(10)https://lodash.com/docs#range

对于数字,您可以使用ES6Array.from()这东西现在什么都能用(IE除外):

更短的版本:

Array.from({length: 20}, (x, i) => i);

较长版本:

Array.from(new Array(20), (x, i) => i);​​​​​​

它创建了一个从0到19的数组。这可以进一步缩短为以下形式之一:

Array.from(Array(20).keys());// or[...Array(20).keys()];

也可以指定下限和上限,例如:

Array.from(new Array(20), (x, i) => i + *lowerBound*);

更详细地描述这一点的文章:http://www.2ality.com/2014/05/es6-array-methods.html

至于为给定范围生成数字数组,我使用:

function range(start, stop){var array = [];
var length = stop - start;
for (var i = 0; i <= length; i++) {array[i] = start;start++;}
return array;}
console.log(range(1, 7));  // [1,2,3,4,5,6,7]console.log(range(5, 10)); // [5,6,7,8,9,10]console.log(range(-2, 3)); // [-2,-1,0,1,2,3]

显然,它不适用于按字母顺序排列的数组。

您可以使用豆沙Undescore.jsrange

var range = require('lodash/range')range(10)// -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

或者,如果你只需要一个连续的整数范围,你可以这样做:

Array.apply(undefined, { length: 10 }).map(Number.call, Number)// -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

在ES6range中可以用发电机实现:

function* range(start=0, end=null, step=1) {if (end == null) {end = start;start = 0;}
for (let i=start; i < end; i+=step) {yield i;}}

此实现在迭代大序列时节省内存,因为它不必将所有值物化到数组中:

for (let i of range(1, oneZillion)) {console.log(i);}

只是在Eloquent JavaScript中做了这样的练习

function range(start, end, step) {var ar = [];if (start < end) {if (arguments.length == 2) step = 1;for (var i = start; i <= end; i += step) {ar.push(i);}}else {if (arguments.length == 2) step = -1;for (var i = start; i >= end; i += step) {ar.push(i);}}return ar;}

Handy函数来完成这个技巧,运行下面的代码片段

function range(start, end, step, offset) {  
var len = (Math.abs(end - start) + ((offset || 0) * 2)) / (step || 1) + 1;var direction = start < end ? 1 : -1;var startingPoint = start - (direction * (offset || 0));var stepSize = direction * (step || 1);  
return Array(len).fill(0).map(function(_, index) {return startingPoint + (stepSize * index);});  
}
console.log('range(1, 5)=> ' + range(1, 5));console.log('range(5, 1)=> ' + range(5, 1));console.log('range(5, 5)=> ' + range(5, 5));console.log('range(-5, 5)=> ' + range(-5, 5));console.log('range(-10, 5, 5)=> ' + range(-10, 5, 5));console.log('range(1, 5, 1, 2)=> ' + range(1, 5, 1, 2));

这里是如何使用它

范围(开始,结束,步骤=1,偏移=0);

  • 包含-前进range(5,10) // [5, 6, 7, 8, 9, 10]
  • 包含-向后range(10,5) // [10, 9, 8, 7, 6, 5]
  • 步骤-后退range(10,2,2) // [10, 8, 6, 4, 2]
  • 排他-转发range(5,10,0,-1) // [6, 7, 8, 9] not 5,10 themselves
  • 偏移-展开range(5,10,0,1) // [4, 5, 6, 7, 8, 9, 10, 11]
  • 偏移-收缩range(5,10,0,-2) // [7, 8]
  • 步骤-展开range(10,0,2,2) // [12, 10, 8, 6, 4, 2, 0, -2]

希望你觉得有用。


这就是它的工作原理。

基本上,我首先计算结果数组的长度,并创建一个零填充数组到该长度,然后用所需的值填充它

  • (step || 1)=>其他类似的表示使用step的值,如果没有提供,则使用1代替
  • 我们首先使用(Math.abs(end - start) + ((offset || 0) * 2)) / (step || 1) + 1)计算结果数组的长度,这样更简单(两个方向/步长的差异*偏移量)
  • 获得长度后,我们使用new Array(length).fill(0);检查这里创建一个带有初始化值的空数组
  • 现在我们有一个数组[0,0,0,..]到我们想要的长度。我们映射它并使用Array.map(function() {})返回一个包含我们需要的值的新数组
  • var direction = start < end ? 1 : 0;显然,如果start不小于end,我们需要向后移动。我的意思是从0到5,反之亦然
  • 在每次迭代中,startingPoint+stepSize*index都会给出我们需要的值
function check(){
var correct=true;
for(var i=0; i<arguments.length; i++){
if(typeof arguments[i] != "number"){
correct=false;  } } return correct; }
//------------------------------------------
function range(start,step,end){
var correct=check(start,step,end);
if(correct && (step && end)!=0){
for(var i=start; i<=end; i+=step)
document.write(i+" "); }
else document.write("Not Correct Data"); }

我会写这样的代码:

function range(start, end) {return Array(end-start).join(0).split(0).map(function(val, id) {return id+start});}
range(-4,2);// [-4,-3,-2,-1,0,1]
range(3,9);// [3,4,5,6,7,8]

它的行为类似于Python范围:

>>> range(-4,2)[-4, -3, -2, -1, 0, 1]

你可以使用带有数组、for循环和Math.random()变量的函数来解决这个问题。for循环将数字推送到数组中,数组将包含你范围内的所有数字。然后Math.random()根据数组的长度随机选择一个。

function randNumInRange(min, max) {var range = []for(var count = min; count <= max; count++) {range.push(count);}var randNum = Math.floor(Math.random() * range.length);alert(range[randNum]);}

解决方案:

//best performancevar range = function(start, stop, step) {var a = [start];while (start < stop) {start += step || 1;a.push(start);}return a;};
//orvar range = function(start, end) {return Array(++end-start).join(0).split(0).map(function(n, i) {return i+start});}

我很惊讶遇到这个线程,没有看到任何像我的解决方案(也许我错过了一个答案),所以在这里。我在ES6语法中使用了一个简单的范围函数:

// [begin, end[const range = (b, e) => Array.apply(null, Array(e - b)).map((_, i) => {return i+b;});

但它只在向前计数时起作用(即开始<结束),所以我们可以在需要时稍微修改它,如下所示:

const range = (b, e) => Array.apply(null, Array(Math.abs(e - b))).map((_, i) => {return b < e ? i+b : b-i;});

我在for循环中使用条件三元运算符(虽然没有参数测试)。

function range(start,end,step){var resar = [];for (var i=start;(step<0 ? i>=end:i<=end); i += (step == undefined ? 1:step)){resar.push(i);};return resar;};

这是我模仿Python的解决方案。在底部,您可以找到一些如何使用它的示例。它适用于数字,就像Python的range一样:

var assert = require('assert');    // if you use Node, otherwise remove the asserts
var L = {};    // L, i.e. 'list'
// range(start, end, step)L.range = function (a, b, c) {assert(arguments.length >= 1 && arguments.length <= 3);if (arguments.length === 3) {assert(c != 0);}
var li = [],i,start, end, step,up = true;    // Increasing or decreasing order? Default: increasing.
if (arguments.length === 1) {start = 0;end = a;step = 1;}
if (arguments.length === 2) {start = a;end = b;step = 1;}
if (arguments.length === 3) {start = a;end = b;step = c;if (c < 0) {up = false;}}
if (up) {for (i = start; i < end; i += step) {li.push(i);}} else {for (i = start; i > end; i += step) {li.push(i);}}
return li;}

示例:

// rangeL.range(0) -> []L.range(1) -> [0]L.range(2) -> [0, 1]L.range(5) -> [0, 1, 2, 3, 4]
L.range(1, 5) -> [1, 2, 3, 4]L.range(6, 4) -> []L.range(-2, 2) -> [-2, -1, 0, 1]
L.range(1, 5, 1) -> [1, 2, 3, 4]L.range(0, 10, 2) -> [0, 2, 4, 6, 8]L.range(10, 2, -1) -> [10, 9, 8, 7, 6, 5, 4, 3]L.range(10, 2, -2) -> [10, 8, 6, 4]

D3还具有内置范围功能。

https://github.com/d3/d3-array#range

d3.range([开始,]停止[,步骤])

生成一个包含算术级数的数组,类似于Python的内置范围。此方法通常用于迭代一系列数字或整数值,例如数组中的索引。与Python版本不同,参数不需要是整数,但如果是浮点精度,结果更可预测。如果省略步骤,它默认为1。

示例:

d3.range(10)// returns [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

如果我们输入类似[4, 2]的东西,我们将得到[2, 3, 4]作为输出,我们可以使用它。

function createRange(array) {var range = [];var highest = array.reduce(function(a, b) {return Math.max(a, b);});var lowest = array.reduce(function(a, b) {return Math.min(a, b);});for (var i = lowest; i <= highest; i++) {range.push(i);}return range;}

编码为2010规格(是的,使用ES6生成器是2016年)。这是我的看法,带有模拟Pythonrange()函数的选项。

Array.range = function(start, end, step){if (start == undefined) { return [] } // "undefined" check
if ( (step === 0) )  {  return []; // vs. throw TypeError("Invalid 'step' input")}  // "step" == 0  check
if (typeof start == 'number') { // number checkif (typeof end == 'undefined') { // single argument inputend = start;start = 0;step = 1;}if ((!step) || (typeof step != 'number')) {step = end < start ? -1 : 1;}
var length = Math.max(Math.ceil((end - start) / step), 0);var out = Array(length);
for (var idx = 0; idx < length; idx++, start += step) {out[idx] = start;}
// Uncomment to check "end" in range() output, non pythonicif ( (out[out.length-1] + step) == end ) { // "end" checkout.push(end)}
} else {// Historical: '&' is the 27th letter: http://nowiknow.com/and-the-27th-letter-of-the-alphabet/// Axiom: 'a' < 'z' and 'z' < 'A'// note: 'a' > 'A' == true ("small a > big A", try explaining it to a kid! )
var st = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&'; // axiom ordering
if (typeof end == 'undefined') { // single argument inputend = start;start = 'a';}
var first = st.indexOf(start);var last = st.indexOf(end);
if ((!step) || (typeof step != 'number')) {step = last < first ? -1 : 1;}
if ((first == -1) || (last == -1 )) { // check 'first' & 'last'return []}
var length = Math.max(Math.ceil((last - first) / step), 0);var out = Array(length);
for (var idx = 0; idx < length; idx++, first += step) {out[idx] = st[first];}
// Uncomment to check "end" in range() output, non pythonicif ( (st.indexOf(out[out.length-1]) + step ) == last ) { // "end" checkout.push(end)}}return out;}

示例:

Array.range(5);       // [0,1,2,3,4,5]Array.range(4,-4,-2); // [4, 2, 0, -2, -4]Array.range('a','d'); // ["a", "b", "c", "d"]Array.range('B','y'); // ["B", "A", "z", "y"], different from chr() orderingArray.range('f');     // ["a", "b", "c", "d", "e", "f"]Array.range(-5);      // [], similar to pythonArray.range(-5,0)     // [-5,-4-,-3-,-2,-1,0]
var range = (l,r) => new Array(r - l).fill().map((_,k) => k + l);

使用range([start,]Stop[, Step])签名完成ES6实现:

function range(start, stop, step=1){if(!stop){stop=start;start=0;}return Array.from(new Array(int((stop-start)/step)), (x,i) => start+ i*step)}

如果你想要自动负步进,添加

if(stop<start)step=-Math.abs(step)

或者更简单地说:

range=(b, e, step=1)=>{if(!e){e=b;b=0}return Array.from(new Array(int((e-b)/step)), (_,i) => b<e? b+i*step : b-i*step)}

如果你有巨大的范围,看看Paolo Moretti的发电机方法

没有本地方法。但您可以使用Arrayfilter方法来完成它。

var range = (array, start, end) =>array.filter((element, index)=>index>=start && index <= end)

alert( range(['a','h','e','l','l','o','s'],1,5) )// ['h','e','l','l','o']

这里有一个很好的简短方法,在ES6中只使用数字(不知道它的速度比较):

Array.prototype.map.call(' '.repeat(1 + upper - lower), (v, i) => i + lower)

对于单个字符的范围,您可以稍微修改它:

Array.prototype.map.call(' '.repeat(1 + upper.codePointAt() - lower.codePointAt()), (v, i) => String.fromCodePoint(i + lower.codePointAt()));

对于字母,他是我想出的一个简单的普通JS解决方案来生成字母范围。它旨在生成大写或小写字母的数组,仅。

function range(first, last) {var r = [],i = first.charCodeAt(0);    
while(i <= last.charCodeAt(0)) {r.push(String.fromCharCode(i++));}    
return r;}
console.dir(range("a", "f"));console.dir(range("G", "Z"));

可以创建一个大量使用ES6的相当简约的实现,如下所示,特别注意#0静态方法:

const getRange = (start, stop) => Array.from(new Array((stop - start) + 1),(_, i) => i + start);

我想补充一下我认为是一个非常可调整的版本,它非常快。

const range = (start, end) => {let all = [];if (typeof start === "string" && typeof end === "string") {// Return the range of characters using utf-8 least to greatestconst s = start.charCodeAt(0);const e = end.charCodeAt(0);for (let i = s; i <= e; i++) {all.push(String.fromCharCode(i));}} else if (typeof start === "number" && typeof end === "number") {// Return the range of numbers from least to greatestfor(let i = end; i >= start; i--) {all.push(i);}} else {throw new Error("Did not supply matching types number or string.");}return all;}// usageconst aTod = range("a", "d");

如果你喜欢打字稿

const range = (start: string | number, end: string | number): string[] | number[] => {const all: string[] | number[] = [];if (typeof start === "string" && typeof end === "string") {const s: number = start.charCodeAt(0);const e: number = end.charCodeAt(0);for (let i = s; i <= e; i++) {all.push(String.fromCharCode(i));}} else if (typeof start === "number" && typeof end === "number") {for (let i = end; i >= start; i--) {all.push(i);}} else {throw new Error("Did not supply matching types number or string.");}return all;}// Usageconst negTenToten: number[] = range(-10, 10) as number[];

受到其他答案的一些影响。用户现在走了。

更新(感谢@lokhmakov的简化)

另一个使用ES6生成器的版本(参见伟大的Paolo Moretti用ES6发电机回答):

const RANGE = (x,y) => Array.from((function*(){while (x <= y) yield x++;})());
console.log(RANGE(3,7));  // [ 3, 4, 5, 6, 7 ]

或者,如果我们只需要可迭代,那么:

const RANGE_ITER = (x,y) => (function*(){while (x <= y) yield x++;})();
for (let n of RANGE_ITER(3,7)){console.log(n);}
// 3// 4// 5// 6// 7

原始代码是:

const RANGE = (a,b) => Array.from((function*(x,y){while (x <= y) yield x++;})(a,b));

const RANGE_ITER = (a,b) => (function*(x,y){while (x <= y) yield x++;})(a,b);

我最喜欢的形式(ES2015

Array(10).fill(1).map((x, y) => x + y)

如果你需要一个step参数的函数:

const range = (start, stop, step = 1) =>Array(Math.ceil((stop - start) / step)).fill(start).map((x, y) => x + y * step)

MDN文档建议的另一个可能的实现:

// Sequence generator function// (commonly referred to as "range", e.g. Clojure, PHP etc)const range = (start, stop, step) =>Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step))

我更喜欢下面的路

var range = function(x, y) {return Array(y - x+1).fill(x).map((a, b) => {return a+b}).filter(i => i >= x);};console.log(range(3, 10));

OK,在JavaScript中,我们没有像php这样的range()函数,所以我们需要创建一个非常简单的函数,我为你写了几个单行函数,并将它们分开数字字母如下:

对于数字

function numberRange (start, end) {return new Array(end - start).fill().map((d, i) => i + start);}

并称其为:

numberRange(5, 10); //[5, 6, 7, 8, 9]

对于字母

function alphabetRange (start, end) {return new Array(end.charCodeAt(0) - start.charCodeAt(0)).fill().map((d, i) => String.fromCharCode(i + start.charCodeAt(0)));}

并称其为:

alphabetRange('c', 'h'); //["c", "d", "e", "f", "g"]

…更多的范围,使用生成器功能。

function range(s, e, str){// create generator that handles numbers & strings.function *gen(s, e, str){while(s <= e){yield (!str) ? s : str[s]s++}}if (typeof s === 'string' && !str)str = 'abcdefghijklmnopqrstuvwxyz'const from = (!str) ? s : str.indexOf(s)const to = (!str) ? e : str.indexOf(e)// use the generator and return.return [...gen(from, to, str)]}
// usage ...console.log(range('l', 'w'))//=> [ 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w' ]
console.log(range(7, 12))//=> [ 7, 8, 9, 10, 11, 12 ]
// first 'o' to first 't' of passed in string.console.log(range('o', 't', "ssshhhooooouuut!!!!"))// => [ 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 't' ]
// only lowercase args allowed here, but ...console.log(range('m', 'v').map(v=>v.toUpperCase()))//=> [ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V' ]
// => and decreasing range ...console.log(range('m', 'v').map(v=>v.toUpperCase()).reverse())
// => ... and with a stepconsole.log(range('m', 'v').map(v=>v.toUpperCase()).reverse().reduce((acc, c, i) => (i % 2) ? acc.concat(c) : acc, []))
// ... etc, etc.

希望这个有用。

有一个npm模块bereich(“bereich”是“range”的德语单词)。它利用了现代JavaScript的迭代器,因此您可以以各种方式使用它,例如:

console.log(...bereich(1, 10));// => 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
const numbers = Array.from(bereich(1, 10));// => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
for (const number of bereich(1, 10)) {// ...}

它还支持降序范围(通过简单地交换minmax),它还支持1以外的步骤。

免责声明:我是本模块的作者,所以请对我的回答持保留态度。

这是我使用的数字范围:

const rangeFrom0 = end => [...Array(end)].map((_, index) => index);

const rangeExcEnd = (start, step, end) => [...Array(end - start + 1)].map((_, index) => index + start).filter(x => x % step === start % step);

这是一个基于@benmcdonald和其他人的简单方法,虽然不止一行…

let K = [];for (i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) {K.push(String.fromCharCode(i))};console.log(K);

您还可以执行以下操作:

const range = Array.from(Array(size)).map((el, idx) => idx+1).slice(begin, end);

没有一个例子有测试,实现步骤与一个选项来产生递减值。

export function range(start = 0, end = 0, step = 1) {if (start === end || step === 0) {return [];}
const diff = Math.abs(end - start);const length = Math.ceil(diff / step);
return start > end? Array.from({length}, (value, key) => start - key * step): Array.from({length}, (value, key) => start + key * step);
}

测试:

import range from './range'
describe('Range', () => {it('default', () => {expect(range()).toMatchObject([]);})
it('same values', () => {expect(range(1,1)).toMatchObject([]);})
it('step=0', () => {expect(range(0,1,0)).toMatchObject([]);})
describe('step=1', () => {it('normal', () => {expect(range(6,12)).toMatchObject([6, 7, 8, 9, 10, 11]);})
it('reversed', () => {expect(range(12,6)).toMatchObject([12, 11, 10, 9, 8, 7]);})})
describe('step=5', () => {
it('start 0 end 60', () => {expect(range(0, 60, 5)).toMatchObject([0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55]);})
it('reversed start 60 end -1', () => {expect(range(55, -1, 5)).toMatchObject([55, 50, 45, 40, 35, 30, 25, 20, 15, 10, 5, 0]);})})})

这是一个范围函数的定义,它的行为与Python的range类型完全相同,除了这个不是懒惰的。将其转换为生成器应该很容易。

范围构造函数的参数必须是数字。如果省略步长参数,则默认为1。如果省略开始参数,则默认为0。如果步长为零,则引发错误。

range = (start, stop, step=1) => {if(step === 0) throw new Error("range() arg 3 must not be zero");
const noStart = stop == null;stop = noStart ? start : stop;start = noStart ? 0 : start;const length = Math.ceil(((stop - start) / step));
return Array.from({length}, (_, i) => (i * step) + start);}
console.log(range(-10, 10, 2));//output [Array] [-10,-8,-6,-4,-2,0,2,4,6,8]console.log(range(10));// [Array] [0,1,2,3,4,5,6,7,8,9]console.log(3, 12);// [Array] [3,4,5,6,7,8,9,10,11]

range(start,end,step):使用ES6迭代器

你只要求一个上限和下限。在这里,我们也创建一个步骤。

您可以轻松创建range()生成器函数,它可以用作迭代器。这意味着您不必预先生成整个数组。

function * range ( start, end, step = 1 ) {let state = start;while ( state < end ) {yield state;state += step;}return;};

现在您可能想要创建一些从迭代器预生成数组并返回列表的东西。这对于接受数组的函数很有用。为此,我们可以使用Array.from()

const generate_array = (start,end,step) =>Array.from( range(start,end,step) );

现在您可以轻松生成静态数组,

const array1 = generate_array(1,10,2);const array1 = generate_array(1,7);

但是当某些东西需要迭代器(或者给你使用迭代器的选项)时,你也可以轻松地创建一个。

for ( const i of range(1, Number.MAX_SAFE_INTEGER, 7) ) {console.log(i)}

特别说明

在边界内生成整数数组的递归解决方案。

function intSequence(start, end, n = start, arr = []) {return (n === end) ? arr.concat(n): intSequence(start, end, start < end ? n + 1 : n - 1, arr.concat(n));}
$> intSequence(1, 1)<- Array [ 1 ]
$> intSequence(1, 3)<- Array(3) [ 1, 2, 3 ]
$> intSequence(3, -3)<- Array(7) [ 3, 2, 1, 0, -1, -2, -3 ]

这个也是反向工作的。

const range = ( a , b ) => Array.from( new Array( b > a ? b - a : a - b ), ( x, i ) => b > a ? i + a : a - i );
range( -3, 2 ); // [ -3, -2, -1, 0, 1 ]range( 1, -4 ); // [ 1, 0, -1, -2, -3 ]

我的codecolfin同事想出了这个(ES6),包括:

(s,f)=>[...Array(f-s+1)].map((e,i)=>i+s)

非包容性:

(s,f)=>[...Array(f-s)].map((e,i)=>i+s)

您可以使用以下单行代码来保持简短

var start = 4;var end = 20;console.log(Array(end - start + 1).fill(start).map((x, y) => x + y));

这可能不是最好的方法。但如果您希望在一行代码中获取一系列数字。例如10-50

Array(40).fill(undefined).map((n, i) => i + 10)

其中40是(结束-开始),10是开始。这应该返回[10,11,50]

// range()              0..10, step=1// range(max)           0..max, step=1// range(min,max)       min..max, step=1// range(min,step,max)  min..max, step=step// Use:// console.log(...range(3));// Array.from(range(5))// [...range(100)]// for (const v of range(1,10)) { ...
function* range(...args) {let [min, step, max] = {0: [0, 1, 10],1: [0, args[0] >= 0 ? 1 : -1, args[0]],2: [args[0], args[1] >= args[0] ? 1 : -1, args[1]],3: args,}[args.length] || [];if (min === undefined) throw new SyntaxError("Too many arguments");let x = min;while (step >= 0 ? x < max : x > max) {yield x;x += step}}console.log(...range());      // 0 1 2 3 4 5 6 7 8 9console.log(...range(3));     // 0 1 2console.log(...range(2, 5));  // 2 3 4console.log(...range(5, 2));  // 5 4 3console.log(...range(3, -3)); // 3 2 1 0 -1 -2console.log(...range(-3, 3)); // -3 -2 -1 0 1 2console.log(...range(-5, -2));// -5 -4 -3console.log(...range(-2, -5));// -2 -3 -4

根据我的理解:

  • JS的运行时环境不支持尾调用优化。编写任何递归函数来生成大范围将带您到这里。
  • 如果我们要处理大数,创建用于循环的数组可能不是最好的做法。
  • 编写大型循环会导致事件队列变慢。
function range(start, end, step = 1) {const _range = _start => f => {if (_start < end) {f(_start);setTimeout(() => _range(_start + step)(f), 0);}}
return {map: _range(start),};}
range(0, 50000).map(console.log);

此功能不会引起上述问题。

具有定义的hard int的范围有大量的答案,但是如果您不知道该步骤并且希望在中间有许多步骤怎么办?

我写了这段代码来做到这一点。这是非常不言自明的。

const stepScale = (min, max, numberOfSteps) => {const _numberOfSteps = numberOfSteps - 1const scaleBy = (max - min) / _numberOfSteps
const arr = []for (let i = 0; i <= _numberOfSteps; i += 1) {arr.push(min + scaleBy * i)}return arr}
export default stepScale
stepScale(5, 10, 4)// [5, 6.666666666666667, 8.333333333333334, 10]

对于npmhttps://npm.im/

保持简单:

// Generatorfunction* iter(a, b, step = 1) {for (let i = b ? a : 0; i < (b || a); i += step) {yield i}}
const range = (a, b, step = 1) =>typeof a === 'string'? [...iter(a.charCodeAt(), b.charCodeAt() + 1)].map(n => String.fromCharCode(n)): [...iter(a, b, step)]
range(4) // [0, 1, 2, 3]range(1, 4) // [1, 2, 3]range(2, 20, 3) // [2, 5, 8, 11, 14, 17]range('A', 'C') // ['A', 'B', 'C']

为了工作,任一给定的数字都可以更大,我写了这个:

function getRange(start, end) {return Array.from({length: 1 + Math.abs(end - start)}, (_, i) => end > start ? start + i : start - i);}

我只是通过Object.definePropertyArray上创建了这个Poly填充来为整数或字符串创建一个范围。Object.defineProperty是创建Poly填充的更安全的方法。

更安全的聚氨酯

if (!Array.range) {Object.defineProperty(Array, 'range', {value: function (from, to, step) {if (typeof from !== 'number' && typeof from !== 'string') {throw new TypeError('The first parameter should be a number or a character')}
if (typeof to !== 'number' && typeof to !== 'string') {throw new TypeError('The second parameter should be a number or a character')}
var A = []if (typeof from === 'number') {A[0] = fromstep = step || 1while (from + step <= to) {A[A.length] = from += step}} else {var s = 'abcdefghijklmnopqrstuvwxyz'if (from === from.toUpperCase()) {to = to.toUpperCase()s = s.toUpperCase()}s = s.substring(s.indexOf(from), s.indexOf(to) + 1)A = s.split('')}return A}})} else {var errorMessage = 'DANGER ALERT! Array.range has already been defined on this browser. 'errorMessage += 'This may lead to unwanted results when Array.range() is executed.'console.log(errorMessage)}

示例

Array.range(1, 3)
// Return: [1, 2, 3]
Array.range(1, 3, 0.5)
// Return: [1, 1.5, 2, 2.5, 3]
Array.range('a', 'c')
// Return: ['a', 'b', 'c']
Array.range('A', 'C')
// Return: ['A', 'B', 'C']
Array.range(null)Array.range(undefined)Array.range(NaN)Array.range(true)Array.range([])Array.range({})Array.range(1, null)
// Return: Uncaught TypeError: The X parameter should be a number or a character

Pythonic风格方式:

range = (start, end, step) => {let arr = []for(let n=start;n<end;n+=(step||1)) arr.push(n)return arr;}
Array.from(Array((m - n + 1)), (v, i) => n + i); // m > n and both of them are integers.

一个可以在任一方向工作的衬垫:

const range = (a,b)=>Array(Math.abs(a-b)+1).fill(a).map((v,i)=>v+i*(a>b?-1:1));

看行动:

const range = (a,b) => Array(Math.abs(a-b)+1).fill(a).map((v,i)=>v+i*(a>b?-1:1));
console.log(range(1,4));console.log(range(4,1));

https://stackoverflow.com/a/49577331/8784402

与三角洲/步骤

最小和单线
[...Array(N)].map((_, i) => from + i * step);

示例和其他替代方案

[...Array(10)].map((_, i) => 4 + i * 2);//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
Array.from(Array(10)).map((_, i) => 4 + i * 2);//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
Array.from(Array(10).keys()).map(i => 4 + i * 2);//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
[...Array(10).keys()].map(i => 4 + i * -2);//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]
Array(10).fill(0).map((_, i) => 4 + i * 2);//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
Array(10).fill().map((_, i) => 4 + i * -2);//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]
范围函数
const range = (from, to, step) =>[...Array(Math.floor((to - from) / step) + 1)].map((_, i) => from + i * step);
range(0, 9, 2);//=> [0, 2, 4, 6, 8]
// can also assign range function as static method in Array class (but not recommended )Array.range = (from, to, step) =>[...Array(Math.floor((to - from) / step) + 1)].map((_, i) => from + i * step);
Array.range(2, 10, 2);//=> [2, 4, 6, 8, 10]
Array.range(0, 10, 1);//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Array.range(2, 10, -1);//=> []
Array.range(3, 0, -1);//=> [3, 2, 1, 0]
作为迭代器
class Range {constructor(total = 0, step = 1, from = 0) {this[Symbol.iterator] = function* () {for (let i = 0; i < total; yield from + i++ * step) {}};}}
[...new Range(5)]; // Five Elements//=> [0, 1, 2, 3, 4][...new Range(5, 2)]; // Five Elements With Step 2//=> [0, 2, 4, 6, 8][...new Range(5, -2, 10)]; // Five Elements With Step -2 From 10//=>[10, 8, 6, 4, 2][...new Range(5, -2, -10)]; // Five Elements With Step -2 From -10//=> [-10, -12, -14, -16, -18]
// Also works with for..of loopfor (i of new Range(5, -2, 10)) console.log(i);// 10 8 6 4 2
仅作为发电机
const Range = function* (total = 0, step = 1, from = 0) {for (let i = 0; i < total; yield from + i++ * step) {}};
Array.from(Range(5, -2, -10));//=> [-10, -12, -14, -16, -18]
[...Range(5, -2, -10)]; // Five Elements With Step -2 From -10//=> [-10, -12, -14, -16, -18]
// Also works with for..of loopfor (i of Range(5, -2, 10)) console.log(i);// 10 8 6 4 2
// Lazy loaded wayconst number0toInf = Range(Infinity);number0toInf.next().value;//=> 0number0toInf.next().value;//=> 1// ...

从到带步骤/增量

使用迭代器
class Range2 {constructor(to = 0, step = 1, from = 0) {this[Symbol.iterator] = function* () {let i = 0,length = Math.floor((to - from) / step) + 1;while (i < length) yield from + i++ * step;};}}[...new Range2(5)]; // First 5 Whole Numbers//=> [0, 1, 2, 3, 4, 5]
[...new Range2(5, 2)]; // From 0 to 5 with step 2//=> [0, 2, 4]
[...new Range2(5, -2, 10)]; // From 10 to 5 with step -2//=> [10, 8, 6]
使用发电机
const Range2 = function* (to = 0, step = 1, from = 0) {let i = 0,length = Math.floor((to - from) / step) + 1;while (i < length) yield from + i++ * step;};
[...Range2(5, -2, 10)]; // From 10 to 5 with step -2//=> [10, 8, 6]
let even4to10 = Range2(10, 2, 4);even4to10.next().value;//=> 4even4to10.next().value;//=> 6even4to10.next().value;//=> 8even4to10.next().value;//=> 10even4to10.next().value;//=> undefined

对于TypeScript

class _Array<T> extends Array<T> {static range(from: number, to: number, step: number): number[] {return Array.from(Array(Math.floor((to - from) / step) + 1)).map((v, k) => from + k * step);}}_Array.range(0, 9, 1);

https://stackoverflow.com/a/64599169/8784402

使用单行生成字符列表

const charList = (a,z,d=1)=>(a=a.charCodeAt(),z=z.charCodeAt(),[...Array(Math.floor((z-a)/d)+1)].map((_,i)=>String.fromCharCode(a+i*d)));
console.log("from A to G", charList('A', 'G'));console.log("from A to Z with step/delta of 2", charList('A', 'Z', 2));console.log("reverse order from Z to P", charList('Z', 'P', -1));console.log("from 0 to 5", charList('0', '5', 1));console.log("from 9 to 5", charList('9', '5', -1));console.log("from 0 to 8 with step 2", charList('0', '8', 2));console.log("from α to ω", charList('α', 'ω'));console.log("Hindi characters from क to ह", charList('क', 'ह'));console.log("Russian characters from А to Я", charList('А', 'Я'));

对于TypeScript
const charList = (p: string, q: string, d = 1) => {const a = p.charCodeAt(0),z = q.charCodeAt(0);return [...Array(Math.floor((z - a) / d) + 1)].map((_, i) =>String.fromCharCode(a + i * d));};

尚未实施!

使用新的Number.range提案(阶段1):

[...Number.range(1, 10)]//=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

我个人的最爱:

const range = (start, end) => new Array(end-start+1).fill().map((el, ind) => ind + start);

使用这个。它创建一个具有给定数量值(未定义)的数组,在以下示例中有100个索引,但它不相关,因为这里你只需要键。它在数组中使用100+1,因为数组总是基于0索引。因此,如果它要生成100个值,索引从0开始;因此最后一个值总是99而不是100。

range(2, 100);
function range(start, end) {console.log([...Array(end + 1).keys()].filter(value => end >= value && start <= value ));}

您可以创建自己的es6系列版本

const range = (min, max) => {const arr = Array(max - min + 1).fill(0).map((_, i) => i + min);return arr;}
console.log(range(0,5));
console.log(range(2,8))

对于行为类似于pythonrange()函数的函数,请使用:

function range(min=0, max=null){if(max === null){max=min;min=0;}var rg=[...Array(max).keys()];return rg.slice(min,max);}

ES6

使用Array.from(docs这里):

const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));

在Vue中遍历0和长度之间的数字范围:

<div v-for="index in range" />
computed: {range () {let x = [];
for (let i = 0; i < this.myLength; i++){x.push(i);}
return x;}}    

如果在Visual Studio Code上遇到错误:

截图

类型'IterableIterator'不是数组类型或字符串类型。使用编译器选项'--down evelIteration'来允许迭代器的迭代。

而不是

[...Array(3).keys()]

你可以依靠

Array.from(Array(3).keys())

更多关于#0

您还可以使用生成器来生成序列。不同之处在于序列中的每个值都是延迟加载的。传播运算符和for of为结果工作。星号符号使函数成为生成器。

const range = function*(from,to) {  for(let i = from; i <= to; i++) yield I;  };  
[...range(3,5)]// => [3, 4, 5]

function range(firstNum, lastNum) {let rangeList = [];if (firstNum > lastNum) {return console.error("First number cannot be bigger than last number");}
let counter = firstNum;while(counter <= lastNum) {rangeList.push(counter);counter++;}
return rangeList;}

(from, to) => [...Array(to - from)].map((_,i)=> i + from)

Op要求一个范围,比如范围(3、10),所以它可以是

[...[...Array(10-3).keys()].map(i => i+3)]

返回

[3, 4, 5, 6, 7, 8, 9]

这是实现您自己的可迭代范围函数的方法。

// implementing rangefunction range(start, end){return {from: start,to: end,
[Symbol.iterator]() {this.current = this.from;return this;},
next() {if (this.current <= this.to) {return { done: false, value: this.current++ };} else {return { done: true };}}};
}
// iterate over each valuefor (let num of range(1,5)) {console.log(num); // 1, 2, 3, 4, 5}

已经给出了非常好的答案,但我没有看到ES6迭代器的完整使用来实现range的完整实现,所以这里是:

/*** inspired by Python's built-in range utility function* implemented using ES6 Iterable, Iterator  protolols (interfaces)*/class Range {constructor(...args) {this.start = args.length <= 1 ? 0 : args[0];this.end = args.length <= 1 ? args[0] || 0 : args[1];this.step = args.length <= 2 ? 1 : args[2];}
[Symbol.iterator]() {return this;}
next() {if (this.end > this.start) {const result = { done: false, value: this.start };this.start = this.start + this.step;return result;} else return { done: true, value: undefined };}}
/*** Symbol.iterator is part of the couple of inbuilt symbols* available in JavaScript. It allows for hooking into the* inbuilt for of iteration mechanism. This is why the* Symbol.iterator comes into play when talking about* iterables and iterators in JavaScript.*/
function range(...args) {return new Range(...args);}
console.log([...range(4)]);        // [0, 1, 2, 3]console.log([...range(2, 5)]);     // [2, 3, 4]console.log([...range(1, 10, 3)]); // [1, 4, 7]

我的实施

export function stringRange(a: string, b: string) {let arr = [a + ''];
const startPrefix = a.match(/([\D])+/g);const endPrefix = b.match(/([\D])+/g);
if ((startPrefix || endPrefix) && (Array.isArray(startPrefix) && startPrefix[0]) !== (Array.isArray(endPrefix) && endPrefix[0])) {throw new Error('Series number does not match');}
const startNum = a.match(/([\d])+/g);const endNum = b.match(/([\d])+/g);
if (!startNum || !endNum) {throw new Error('Range is not valid');}
let start = parseInt(startNum[0], 10);let end = parseInt(endNum[0], 10);
if (start > end) {throw new Error('Ending value should be lessesr that starting value');}
while (start !== end) {start++;arr.push(startPrefix ? startPrefix[0] + (start + '').padStart(startNum[0].length, '0') : start + '');
}
return arr;}

示例结果

// console.log(range('0', '10'));// console.log(range('10', '10'));// console.log(range('10', '20'));// console.log(range('10', '20000'));// console.log(range('ABC10', 'ABC23'));// console.log(range('ABC10', 'ABC2300'));// console.log(range('ABC10', 'ABC09')); --> Failure case// console.log(range('10', 'ABC23')); --> Failure case// console.log(range('ABC10', '23')); --> Failure case

使用TypeScript设置(应用范围):

declare global {interface Function {range(count: number, start_with: number): number[];}}
Function.prototype.range = function (count: number,start_with: number = 0): number[] {return [...Array(count).keys()].map((key) => key + start_with);};

使用JS设置

Function.prototype.range = function(count, start_with=0){return [...Array(count).keys()].map((key) => key + start_with);}

使用示例

Function.range(2,0) //Will return [0,1]Function.range(2,1) //Will return [1,2]Function.range(2,-1) //Will return [-1,0]

我最喜欢的是带有另一个函数getRange的生成器generateRange来运行生成器。与许多其他解决方案相比,这种方法的一个优点是不会多次创建不必要的数组。

function* generateRange(start, end, step = 1) {let current = start;while (start < end ? current <= end : current >= end) {yield current;current = start < end ? current + step : current - step;}}
function getRange(start, end, step = 1) {return [...generateRange(start, end, step)];}
console.log(getRange(0, 5)) // [ 0, 1, 2, 3, 4, 5 ]console.log(getRange(10, 0, 2)) // [ 10, 8, 6, 4, 2, 0 ]
/*** @param {!number|[!number,!number]} sizeOrRange Can be the `size` of the range (1st signature) or a*   `[from, to]`-shape array (2nd signature) that represents a pair of the *starting point (inclusive)* and the*   *ending point (exclusive)* of the range (*mathematically, a left-closed/right-open interval: `[from, to)`*).* @param {!number} [fromOrStep] 1st signature: `[from=0]`. 2nd signature: `[step=1]`* @param {!number} [stepOrNothing] 1st signature: `[step=1]`. 2nd signature: NOT-BEING-USED* @example* range(5) ==> [0, 1, 2, 3, 4] // size: 5* range(4, 5)    ==> [5, 6, 7, 8]  // size: 4, starting from: 5* range(4, 5, 2) ==> [5, 7, 9, 11] // size: 4, starting from: 5, step: 2* range([2, 5]) ==> [2, 3, 4] // [2, 5) // from: 2 (inclusive), to: 5 (exclusive)* range([1, 6], 2) ==> [1, 3, 5] // from: 1, to: 6, step: 2* range([1, 7], 2) ==> [1, 3, 5] // from: 1, to: 7 (exclusive), step: 2* @see {@link https://stackoverflow.com/a/72388871/5318303}*/export function range (sizeOrRange, fromOrStep, stepOrNothing) {let from, to, step, sizeif (sizeOrRange instanceof Array) { // 2nd signature: `range([from, to], step)`[from, to] = sizeOrRangestep = fromOrStep ?? 1size = Math.ceil((to - from) / step)} else { // 1st signature: `range(size, from, step)`size = sizeOrRangefrom = fromOrStep ?? 0step = stepOrNothing ?? 1}return Array.from({length: size}, (_, i) => from + i * step)}

示例:

console.log(range(5), // [0, 1, 2, 3, 4] // size: 5range([2, 5]), // [2, 3, 4] // [2, 5) // from: 2 (inclusive), to: 5 (exclusive)range(4, 2), // [2, 3, 4, 5] // size: 4, starting from: 2range([1, 6], 2), // [1, 3, 5] // from: 1, to: 6, step: 2range([1, 7], 2), // [1, 3, 5] // from: 1, to: 7 (exclusive), step: 2)
<script>function range (sizeOrRange, fromOrStep, stepOrNothing) {let from, to, step, sizeif (sizeOrRange instanceof Array) { // 2nd signature: `range([from, to], step)`[from, to] = sizeOrRangestep = fromOrStep ?? 1size = Math.ceil((to - from) / step)} else { // 1st signature: `range(size, from, step)`size = sizeOrRangefrom = fromOrStep ?? 0step = stepOrNothing ?? 1}return Array.from({ length: size }, (_, i) => from + i * step)}</script>

Javascript提供了一个函数来从给定值创建和填充数组,接收容器数组和map函数作为参数:

let arr = Array.from(SOURCE_ARRAY, MAP_FUNCTION);

由于MAP_FUNCTION为迭代提供了值和索引,因此可以创建一个空数组(SOURCE_ARRAY)并使用索引填充它,如下所示(假设10是您想要的长度):

let arr = Array.from(Array(10), (n, index) => index);

输出:[0,1,2,3,4,5,6,7,8,9]。

用于紧密复制的打字稿功能

/*** Create a generator from 0 to stop, useful for iteration. Similar to range in Python.* See: https://stackoverflow.com/questions/3895478/does-javascript-have-a-method-like-range-to-generate-a-range-within-the-supp* See: https://docs.python.org/3/library/stdtypes.html#ranges* @param {number | BigNumber} stop* @returns {Iterable<number>}*/export function range(stop: number | BigNumber): Iterable<number>/*** Create a generator from start to stop, useful for iteration. Similar to range in Python.* See: https://stackoverflow.com/questions/3895478/does-javascript-have-a-method-like-range-to-generate-a-range-within-the-supp* See: https://docs.python.org/3/library/stdtypes.html#ranges* @param {number | BigNumber} start* @param {number | BigNumber} stop* @returns {Iterable<number>}*/export function range(start: number | BigNumber,stop: number | BigNumber,): Iterable<number>
/*** Create a generator from start to stop while skipping every step, useful for iteration. Similar to range in Python.* See: https://stackoverflow.com/questions/3895478/does-javascript-have-a-method-like-range-to-generate-a-range-within-the-supp* See: https://docs.python.org/3/library/stdtypes.html#ranges* @param {number | BigNumber} start* @param {number | BigNumber} stop* @param {number | BigNumber} step* @returns {Iterable<number>}*/export function range(start: number | BigNumber,stop: number | BigNumber,step: number | BigNumber,): Iterable<number>export function* range(a: unknown, b?: unknown, c?: unknown): Iterable<number> {const getNumber = (val: unknown): number =>typeof val === 'number' ? val : (val as BigNumber).toNumber()const getStart = () => (b === undefined ? 0 : getNumber(a))const getStop = () => (b === undefined ? getNumber(a) : getNumber(b))const getStep = () => (c === undefined ? 1 : getNumber(c))
for (let i = getStart(); i < getStop(); i += getStep()) {yield i}}

我在这里回顾了答案,并注意到以下几点:

  • JavaScript没有针对此问题的内置解决方案
  • 一些答案生成一个大小正确但值错误的数组
    • 例如let arr = Array.from( {length:3} ); // gives [null,null,null]
  • 然后,使用映射函数将错误的值替换为正确的值
    • 例如arr.map( (e,i) => i ); // gives [0,1,2]
  • 数学需要移动数字范围以满足fromto要求。
    • 例如arr.map( (e,i) => i+1 ); // gives [1,2,3]
  • 对于问题的字符串版本,需要charCodeAtfromCharCode将字符串映射到一个数字,然后再次返回到一个字符串。
    • 例如arr.map( (e,i) => String.fromCharCode( i+"A".charCodeAt(0) ); // gives ["A","B","C"]

基于上述部分或全部,有一些简单到一些花哨的实现。当他们试图将整数和字符串解决方案打包到一个函数中时,答案变得复杂了。对我来说,我选择在他们自己的函数中实现整数和字符串解决方案。我证明了这一点,因为在实践中,你会知道你的用例是什么,你将直接使用适当的函数。如果你想间接调用它,我还提供包装函数。

let rangeInt = (from,to) => Array.from( { length: to-from+1 }, (e, i) => i + from );let rangeChar = (from,to) => Array.from( { length: to.charCodeAt(0)-from.charCodeAt(0)+1 }, (e,i) => String.fromCharCode(i+from.charCodeAt(0)) );let range = (from,to) =>(typeof(from) === 'string' && typeof(to) === 'string')? rangeChar(from,to): (!to) ? rangeInt(0,from-1) : rangeInt(from,to);
console.log( rangeInt(1,3) ); // gives [1,2,3]console.log( rangeChar("A","C") ); // gives ["A","B","C"]console.log( range(1,3) ); // gives [1,2,3]console.log( range("A","C") ); // gives ["A","B","C"]console.log( range(3) ); // gives [0,1,2]

nope——在2002年仍然没有原生的javascriptrange,但是这个简洁的ES6箭头函数可以像php一样提供升序和降序数字和字符串(包括步骤)。

// @return ascending or descending range of numbers or stringsconst range = (a,b,d=1) => typeof a === 'string'? range(a.charCodeAt(),b.charCodeAt()).map(v=>String.fromCharCode(v)): isNaN(b)? range(0, a-1): b < a? range(b, a, d).reverse(): d > 1? range(a, b).filter(v => v%d === 0): [a,b].reduce((min,max)=>Array(max+1-min).fill(min).map((v,i)=>v+i));
// Usageconsole.assert(range(3).toString() === '0,1,2' &&range(2,4).toString() === '2,3,4' &&range(4,2).toString() === '4,3,2' &&range(5,15,5).toString() === '5,10,15' &&range('A','C').toString() === 'A,B,C' &&range('C','A').toString() === 'C,B,A');

我找到的最接近的是radash库:

import { range } from 'radash'
for (let i of range(1, 5)) {console.log(i)}

看这里留档:

range-Radash