在PHP中,您可以。。。

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

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

JavaScript本机是否有内置的功能?如果没有,我将如何实施?


当前回答

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

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

请参阅实际操作:

常量范围=(a,b)=>数组(数学.abs(a-b)+1).fill(a).map((v,i)=>v+i*(a>b?-1:1));console.log(范围(1,4));console.log(范围(4,1));

其他回答

保持简单:

// Generator
function* 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']

使用范围([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)
}

如果你有巨大的射程,看看保罗·莫雷蒂的发电机方法

编码为2010年规格(是的,2016年是ES6发电机)。这是我的想法,其中包含模拟Python的range()函数的选项。

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 check
        if (typeof end == 'undefined') { // single argument input
            end = 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 pythonic
        if ( (out[out.length-1] + step) == end ) { // "end" check
            out.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 input
            end = 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 pythonic
        if ( (st.indexOf(out[out.length-1]) + step ) == last ) { // "end" check
            out.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() ordering
Array.range('f');     // ["a", "b", "c", "d", "e", "f"]
Array.range(-5);      // [], similar to python
Array.range(-5,0)     // [-5,-4-,-3-,-2,-1,0]

这里有一个npm模块bereich(“bereich”是德语中“范围”的意思)。它利用了现代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)) {
  // ...
}

它还支持递减范围(通过简单地交换最小值和最大值),并且还支持除1以外的步骤。

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

它适用于字符和数字,通过可选步骤向前或向后移动。

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范围=函数(开始、结束、步骤){var范围=[];var typeofStart=启动类型;var typeofEnd=结束类型;如果(步骤==0){throw TypeError(“步长不能为零。”);}if(类型开始==“undefined”| |类型结束==“未定义”){throw TypeError(“必须传递开始和结束参数。”);}否则如果(typeofStart!=typeofEnd){throw TypeError(“开始和结束参数必须是相同的类型。”);}步骤类型==“未定义”&&(步骤=1);if(结束<开始){step=-步骤;}if(开始类型==“number”){while(步骤>0?结束>=开始:结束<=开始){范围.推(启动);开始+=步骤;}}否则if(typeofStart==“string”){如果(start.length!=1 | | end.length;=1){throw TypeError(“仅支持带有一个字符的字符串。”);}start=start.charCodeAt(0);end=end.charCodeAt(0);while(步骤>0?结束>=开始:结束<=开始){range.push(String.fromCharCode(开始));开始+=步骤;}}其他{throw TypeError(“仅支持字符串和数字类型”);}返回范围;}console.log(范围(“A”,“Z”,1));console.log(范围(“Z”,“A”,1));console.log(范围(“A”,“Z”,3));console.log(范围(0,25,1));console.log(范围(0,25,5));console.log(范围(20,5,5));