在PHP中,您可以。。。

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

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

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


当前回答

/**
 * @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, size
  if (sizeOrRange instanceof Array) { // 2nd signature: `range([from, to], step)`
    [from, to] = sizeOrRange
    step = fromOrStep ?? 1
    size = Math.ceil((to - from) / step)
  } else { // 1st signature: `range(size, from, step)`
    size = sizeOrRange
    from = fromOrStep ?? 0
    step = stepOrNothing ?? 1
  }
  return Array.from({length: size}, (_, i) => from + i * step)
}

示例:

控制台日志(范围(5),//[0,1,2,3,4]//size:5范围([2,5]),//[2,3,4]//[2、5)//从:2(含)到:5(不含)范围(4,2),//[2,3,4,5]//大小:4,从:2开始范围([1,6],2),//[1,3,5]//从:1到:6,步骤:2范围([1,7],2),//[1,3,5]//从:1到:7(不含),步骤:2)<脚本>函数范围(sizeOrRange、fromOrStep、stepOrNothing){让从、到、步长、大小if(sizeOrRange instanceof Array){//第二个签名:`range([from,to],step)`[from,to]=sizeOrRange步骤=来自或步骤??1.size=数学ceil((to-from)/步长)}else{//第一个签名:`range(大小,从,步)`size=sizeOrRangefrom=来自或步骤??0step=stepOrNothing??1.}return Array.from({length:size},(_,i)=>from+i*step)}</script>

其他回答

我的代码高尔夫同事想出了这个(ES6),包容的:

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

非包容性:

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

使用Harmony排列运算符和箭头函数:

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

例子:

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

这是我用于数字范围的方法:

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

or

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

我最喜欢的新形式(ES2015)

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

如果您需要一个带有步骤参数的函数:

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

没有一个示例进行了测试,每个步骤都有一个生成递减值的选项。

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