关于数组:JavaScript是否有像“range()”这样的方法来生成提供的范围内的范围?

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

在PHP中,你可以做...

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

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

是否内置了JavaScript本身的内容? 如果没有,我将如何实施它?


数字

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

字符迭代

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

迭代

1
2
3
4
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"

作为功??能

1
2
3
4
5
6
7
8
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)))
}

作为打字功能

1
2
3
4
5
6
7
8
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()功能

1
2
3
4
5
6
7
8
9
10
_.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浏览器:

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

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

谢谢。

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


对于数字,你可以使用ES6 Array.from(),这些日子除了IE以外的所有东西都可以使用:

更短的版本:

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

更长的版本:

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

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

1
2
3
Array.from(Array(20).keys())
// or
[...Array(20).keys()]

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

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

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


我最喜欢的表格(ES2015)

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

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

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


这是我的2美分:

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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));


简单的范围功能:

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


好的,在JavaScript中我们没有像PHP那样的range()函数,所以我们需要创建一个非常简单的函数,我为你编写几个单行函数,并将它们分别用于Numbers和Alphabets,如下所示:

对于数字:

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

并称之为:

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

对于字母:

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

并称之为:

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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']

方便的功能来完成这个技巧,运行下面的代码片段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
  • offset - 展开range(5,10,0,1) // [4, 5, 6, 7, 8, 9, 10, 11]
  • offset - 收缩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将为我们提供所需的值


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


使用Harmony传播操作符和箭头函数:

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

例:

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


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

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


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

获胜者是......

1
2
3
4
5
6
7
8
9
function range(lowEnd,highEnd){
    var arr = [],
    c = highEnd - lowEnd + 1;
    while ( c-- ) {
        arr[c] = highEnd--
    }
    return arr;
}
range(0,31);

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

同样有趣的观察是这些数组函数的速度比firefox快多少。 Chrome的速度至少快4到5倍。


您可以使用lodash或Undescore.js range

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

或者,如果您只需要一个连续的整数范围,您可以执行以下操作:

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

在ES6中,range可以用生成器实现:

1
2
3
4
5
6
7
8
9
10
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;
  }
}

这种实现在迭代大型序列时可以节省内存,因为它不必将所有值都实现为数组:

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


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

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

console.log(RANGE(3,7));  // [ 3, 4, 5, 6, 7 ]

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

1
2
3
4
5
6
7
8
9
10
11
12
13
const RANGE_ITER = (a,b) => (function*(x,y){
  while (x <= y) yield x++;
})(a,b);

for (let n of RANGE_ITER(3,7)){
  console.log(n);
}

// 3
// 4
// 5
// 6
// 7

一个有趣的挑战是编写最短的函数来做到这一点。救援的递归!

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

在大范围内趋于缓慢,但幸运的是量子计算机即将到来。

一个额外的好处是它是混淆的。因为我们都知道将我们的代码隐藏起来是多么重要。

要真正彻底地混淆函数,请执行以下操作:

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


可以如下创建大量使用ES6的相当简约的实现,特别注意Array.from()静态方法:

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


我会编码这样的代码:

1
2
3
4
5
6
7
8
9
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范围:

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

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

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

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

1
2
3
4
5
6
7
8
function * range ( start, end, step = 1 ) {
  let state = start;
  while ( state < end ) {
    yield state;
    state += step;
  }
  return;
};

现在,您可能希望创建从迭代器预生成数组并返回列表的内容。这对接受数组的函数很有用。为此,我们可以使用Array.from()

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

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

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

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

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

特别说明

  • 如果你使用Ramda,他们有自己的R.range和Lodash一样

虽然这不是来自PHP,而是来自Python的range模仿。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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]


使用Harmony生成器,除IE11以外的所有浏览器都支持:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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不是必要的

<5233>

回报

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

takeAll

例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"]


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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]

显然,它不适用于字母数组。


...更多范围,使用发电机功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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 step
console.log(range('m', 'v')
          .map(v=>v.toUpperCase())
          .reverse()
          .reduce((acc, c, i) => (i % 2) ? acc.concat(c) : acc, []))

// ... etc, etc.

希望这很有用。


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


d3还具有内置范围功能。请参阅https://github.com/mbostock/d3/wiki/Arrays#d3_range:

d3.range([start, ]stop[, step])

Generates an array containing an arithmetic progression, similar to the Python built-in range. This method is often used to iterate over a sequence of numeric or integer values, such as the indexes into an array. Unlike the Python version, the arguments are not required to be integers, though the results are more predictable if they are due to floating point precision. If step is omitted, it defaults to 1.

例:

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


使用范围([start,] stop [,step])签名完成ES6实现:

1
2
3
4
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)
}

如果您想要自动消极步进,请添加

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

或者更简约:

1
2
3
4
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的发电机方法


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

1
2
3
4
5
6
7
8
9
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以外的步骤。

免责声明:我是本单元的作者,所以请尽量回答我的问题。


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

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

对于一系列单个字符,您可以稍微修改它:

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

您还可以执行以下操作:

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

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

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

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

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


这个也是相反的。

1
2
3
4
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 ]

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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);

}

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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]);
        })
    })
})

我的代码冲突同事想出了这个(ES6),
包括的:

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

非包容性:

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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 ]


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

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

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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;
}

这是缩小版:

1
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};

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

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

1
2
3
4
5
6
7
8
9
10
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;
}

例子:

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


没有本地方法。但是你可以用Array Array方法做到这一点。

1
2
3
4
5
6
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']


您可以使用以下单行来简化和简单

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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;
}

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// range
L.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]

这是一个范围函数的定义,其行为与Python的range类型完全相同,只是这个函数不是惰性的。将它变成发电机应该很容易。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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]

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

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


这是我用于数字范围的内容:

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

要么

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

我更喜欢下面的方式

1
2
3
4
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));


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

1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}


对于信件,他是一个简单的香草JS解决方案,我想出来生成字母范围。它仅用于生成大写或小写字母的数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
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"));


编码为2010年规格(ya,2016年是ES6发电机)。这是我的看法,可以选择模拟Python的range()函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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;
}

例:

1
2
3
4
5
6
7
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]

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

1
2
3
4
5
6
7
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;
};


解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//best performance
var range = function(start, stop, step) {
    var a = [start];
    while (start < stop) {
        start += step || 1;
        a.push(start);
    }
    return a;
};

//or
var range = function(start, end) {
    return Array(++end-start).join(0).split(0).map(function(n, i) {
        return i+start
    });
}


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const range = (start, end) => {
    let all = [];
    if (typeof start ==="string" && typeof end ==="string") {
        // Return the range of characters using utf-8 least to greatest
        const 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 greatest
        for(let i = end; i >= start; i--) {
            all.push(i);
        }
    } else {
        throw new Error("Did not supply matching types number or string.");
    }
    return all;
}
// usage
const aTod = range("a","d");

如果你愿意,也可以打字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;
}
// Usage
const negTenToten: number[] = range(-10, 10) as number[];

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


在Eloquent JavaScript中做了类似这样的练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
}

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

1
2
3
4
5
6
7
8
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]);
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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"); }