JavaScript 有没有像“range()”这样的方法来在提供的范围内生成一个范围?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3895478/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:32:55  来源:igfitidea点击:

Does JavaScript have a method like "range()" to generate a range within the supplied bounds?

javascriptarraysfunctional-programming

提问by alex

In PHP, you can do...

在 PHP 中,你可以做...

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

That is, there is a function that lets you get a range of numbers or characters by passing the upper and lower bounds.

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

Is there anything built-in to JavaScript natively for this? If not, how would I implement it?

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

采纳答案by alex

It works for characters and numbers, going forwards or backwards with an optional step.

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

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.

js小提琴

If augmenting native types is your thing, then assign it to Array.range.

如果您喜欢扩充本机类型,则将其分配给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));

回答by Ben

Numbers

数字

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

Character iteration

字符迭代

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

Iteration

迭代

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"

As functions

作为函数

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)))
}

As typed functions

作为类型函数

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 _.range()function

lodash.js_.range()函数

_.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"

Old non es6 browsers without a library:

没有库的旧非 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)

(ES6 归功于 nils petersohn 和其他评论者)

回答by Kristjan Liiva

For numbers you can use ES6 Array.from(), which works in everything these daysexcept IE:

对于数字,您可以使用 ES6 Array.from()现在除了 IE 之外,它适用于所有事物

Shorter version:

较短的版本:

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

Longer version:

更长的版本:

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

which creates an array from 0 to 19 inclusive. This can be further shortened to one of these forms:

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

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

Lower and upper bounds can be specified too, for example:

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

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

An article describing this in more detail: http://www.2ality.com/2014/05/es6-array-methods.html

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

回答by Kutyel

My new favorite form (ES2015)

我最喜欢的新表格(ES2015

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

And if you need a function with a stepparam:

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

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

回答by jflood.net

Here's my 2 cents:

这是我的 2 美分:

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

回答by Remi

Simple range function:

简单的范围函数:

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


To incorporate the BitInt data typesome check can be included, ensuring that all variables are same typeof start:

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

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


To remove values higher than defined by stope.g. range(0,5,2)will include 6, which shouldn't be.

删除高于stopeg定义的值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;
}

回答by kennebec

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']

回答by Alireza

OK,in JavaScript we don't have a range()function like PHP, so we need to create the function which is quite easy thing, I write couple of one-line functions for you and separate them for Numbersand Alphabetsas below:

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

for Numbers:

对于数字

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

and call it like:

并称之为:

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

for Alphabets:

对于字母

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

and call it like:

并称之为:

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

回答by azerafati

Handyfunction to do the trick, run the code snippet below

实用的功能,运行下面的代码片段

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));

here is how to use it

这是如何使用它

range (Start, End, Step=1, Offset=0);

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

  • inclusive - forward range(5,10) // [5, 6, 7, 8, 9, 10]
  • inclusive - backward range(10,5) // [10, 9, 8, 7, 6, 5]
  • step - backward range(10,2,2) // [10, 8, 6, 4, 2]
  • exclusive - forward range(5,10,0,-1) // [6, 7, 8, 9] not 5,10 themselves
  • offset - expand range(5,10,0,1) // [4, 5, 6, 7, 8, 9, 10, 11]
  • offset - shrink range(5,10,0,-2) // [7, 8]
  • step - expand range(10,0,2,2) // [12, 10, 8, 6, 4, 2, 0, -2]
  • 包容 - 向前 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]

hope you find it useful.

希望你觉得它有用。



And here is how it works.

这是它的工作原理。

Basically I'm first calculating the length of the resulting array and create a zero filled array to that length, then fill it with the needed values

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

  • (step || 1)=> And others like this means use the value of stepand if it was not provided use 1instead
  • We start by calculating the length of the result array using (Math.abs(end - start) + ((offset || 0) * 2)) / (step || 1) + 1)to put it simpler (difference* offset in both direction/step)
  • After getting the length, then we create an empty array with initialized values using new Array(length).fill(0);check here
  • Now we have an array [0,0,0,..]to the length we want. We map over it and return a new array with the values we need by using Array.map(function() {})
  • var direction = start < end ? 1 : 0;Obviously if startis not smaller than the endwe need to move backward. I mean going from 0 to 5 or vice versa
  • On every iteration, startingPoint+ stepSize* indexwill gives us the value we need
  • (step || 1)=> 和其他类似的意思是使用的值,step如果没有提供,请1改用
  • 我们首先计算结果数组的长度,用(Math.abs(end - start) + ((offset || 0) * 2)) / (step || 1) + 1)更简单的方式(在两个方向/步长上的 差异*偏移)
  • 获得长度后,我们使用check here创建一个带有初始化值的空数组new Array(length).fill(0);
  • 现在我们有一个[0,0,0,..]我们想要的长度的数组。我们映射它并使用我们需要的值返回一个新数组Array.map(function() {})
  • var direction = start < end ? 1 : 0;显然如果start不小于end我们需要向后移动。我的意思是从 0 到 5,反之亦然
  • 在每次迭代中,startingPoint+ stepSize*index都会给我们需要的值

回答by Klesun

var range = (l,r) => new Array(r - l).fill().map((_,k) => k + l);