JavaScript函数类似Python范围()

clw*_*wen 75 javascript python

JavaScript中的函数是否类似于Python range()

我认为应该有一个更好的方法,而不是每次写下面的行:

array = new Array();
for (i = 0; i < specified_len; i++) {
    array[i] = i;
}
Run Code Online (Sandbox Code Playgroud)

小智 92

对于ES6中非常简单的范围:

let range = n => Array.from(Array(n).keys())
Run Code Online (Sandbox Code Playgroud)

  • 更简单的版本是`let range = n => [... Array(n).keys()]` (33认同)
  • 这个答案没有考虑起始索引和增加步长的能力。 (11认同)
  • @BharathRaja 很棒,谢谢!为什么不是常量?我会尽量使用 const :) 就像 Java 最终版本一样 ;) (2认同)

Tad*_*eck 79

,没有,但你可以做一个.

JavaScript的Python实现 range()

试图模仿它在Python中的工作方式,我会创建类似于这样的函数:

function range(start, stop, step) {
    if (typeof stop == 'undefined') {
        // one param defined
        stop = start;
        start = 0;
    }

    if (typeof step == 'undefined') {
        step = 1;
    }

    if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
        return [];
    }

    var result = [];
    for (var i = start; step > 0 ? i < stop : i > stop; i += step) {
        result.push(i);
    }

    return result;
};
Run Code Online (Sandbox Code Playgroud)

请参阅此jsfiddle以获取证据.

range()JavaScript和Python 之间的比较

它的工作方式如下:

  • range(4)回来[0, 1, 2, 3],
  • range(3,6)回来[3, 4, 5],
  • range(0,10,2)回来[0, 2, 4, 6, 8],
  • range(10,0,-1)回来[10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
  • range(8,2,-2)回来[8, 6, 4],
  • range(8,2)回来[],
  • range(8,2,2)回来[],
  • range(1,5,-1)回来[],
  • range(1,5,-2)回来[],

它的Python对应方式完全相同(至少在上述情况下):

>>> range(4)
[0, 1, 2, 3]
>>> range(3,6)
[3, 4, 5]
>>> range(0,10,2)
[0, 2, 4, 6, 8]
>>> range(10,0,-1)
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> range(8,2,-2)
[8, 6, 4]
>>> range(8,2)
[]
>>> range(8,2,2)
[]
>>> range(1,5,-1)
[]
>>> range(1,5,-2)
[]
Run Code Online (Sandbox Code Playgroud)

因此,如果您需要一个与Python类似的功能range(),您可以使用上述解决方案.

  • 也许是一些额外的防御性检查 - 确保传递的参数都可以强制数字并确保`stop`大于`start`(如果没有则交换它们). (4认同)

geo*_*org 27

2018年:这个答案不断上升,所以这是一个更新.下面的代码已经过时,但幸运的是ES6标准化生成器和yield关键字,它们在不同平台上得到普遍支持.可以在此处找到惰性range()使用的示例. yield


除了那些已经萨义德的,使用Javascript 1.7+提供了支持迭代器和发电机可用于创建一个懒惰的,节省内存的版本range,simlar到xrange在Python2:

function range(low, high) {  
    return {
        __iterator__: function() {
            return {  
                next: function() {
                    if (low > high)
                        throw StopIteration;  
                    return low++;
                }
            }
        }
    }
}

for (var i in range(3, 5))  
  console.log(i); // 3,4,5
Run Code Online (Sandbox Code Playgroud)


Mar*_*ery 18

Python range函数的一个端口由underscore.jslodash实用程序库(以及许多其他有用的工具)提供.从下划线文档复制的示例:

_.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]
_.range(0);
=> []
Run Code Online (Sandbox Code Playgroud)


jan*_*102 16

@Tadeck@georg的答案融合在一起,我想出了这个:

function* range(start, stop, step = 1) {
    if (typeof stop === 'undefined') {
        // one param defined
        stop = start;
        start = 0;
    }

    for (let i = start; step > 0 ? i < stop : i > stop; i += step) {
        yield i;
    }
}
Run Code Online (Sandbox Code Playgroud)

要在for循环中使用它,您需要ES6/JS1.7 for-of循环:

for (let i of range(0, 10, 2)) {
    console.log(i);
}
// Outputs => 0 2 4 6 8
Run Code Online (Sandbox Code Playgroud)

  • WTG,这是迄今为止最好的实现。它使用生成器(很好,因为不需要将整个序列存储在内存中)并且非常简洁。 (2认同)

mch*_*cha 12

可以通过将迭代器附加到Number原型来实现

  Number.prototype[Symbol.iterator] = function* () { 
     for (var i = 0; i <= this; i++) {
       yield i
     } 
  }

[...5] // will result in [0,1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

摘自Kyle Simpson的课程重新思考异步JavaScript

  • 这真的很酷,但是压倒一切的原型太脆弱了:'( (5认同)
  • 这实际上使数字可迭代,试试这个:`for (var i of 5) { console.log(i); }` (2认同)

Rig*_*red 7

干得好.

这将使用索引号写入(或覆盖)每个索引的值.

Array.prototype.writeIndices = function( n ) {
    for( var i = 0; i < (n || this.length); ++i ) this[i] = i;
    return this;
};
Run Code Online (Sandbox Code Playgroud)

如果您没有提供数字,它将使用数组的当前长度.

像这样使用它:

var array = [].writeIndices(10);  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)


Dmi*_*lov 6

如果需要同时指定范围的开始和结束位置,以下是其中一个答案的小扩展名:

let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);
Run Code Online (Sandbox Code Playgroud)


Key*_*van 6

pythonicrange使用 JS 的生成器 ( yield)最好地模仿 Python行为,支持range(stop)range(start, stop, step)用例。此外,pythonicrange函数返回一个Iterator类似于 Python的对象,它支持mapfilter,因此可以做一些花哨的单行代码,例如:

import {range} from 'pythonic';
// ...
const results = range(5).map(wouldBeInvokedFiveTimes);
// `results` is now an array containing elements from
// 5 calls to wouldBeInvokedFiveTimes
Run Code Online (Sandbox Code Playgroud)

安装使用npm

npm install --save pythonic
Run Code Online (Sandbox Code Playgroud)

披露我是 Pythonic 的作者和维护者


小智 6

对于任何寻求现代解决方案的人 [...Array(n).keys()]


小智 5

使用 ES6 默认参数进一步细化。

let range = function*(start = 0, stop, step = 1) {
  let cur = (stop === undefined) ? 0 : start;
  let max = (stop === undefined) ? start : stop;
  for (let i = cur; step < 0 ? i > max : i < max; i += step)
    yield i
}
Run Code Online (Sandbox Code Playgroud)


big*_*ega 5

为了获得 size 的数组x,这是一个不使用任何库的单行

var range = n => Array(n + 1).join(1).split('').map((x, i) => i)
Run Code Online (Sandbox Code Playgroud)

作为

> range(4)
[0, 1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

  • `var range = n =&gt; Array(n).fill().map((e, i) =&gt; i);` (2认同)

le_*_*e_m 5

以下是Python的range()函数对JavaScript 的自然适应:

// Generate range from start (inclusive) to stop (exclusive):
function* range(start, stop, step = 1) {
   if (stop === undefined) [start, stop] = [0, start];
   if (step > 0) while (start < stop) yield start, start += step;
   else if (step < 0) while (start > stop) yield start, start += step;
   else throw new RangeError('range() step argument invalid');
} 

// Examples:
console.log([...range(3)]);       // [0, 1, 2]
console.log([...range(0, 3)]);    // [0, 1, 2]
console.log([...range(0, 3, -1)]);// []
console.log([...range(0, 0)]);    // []
console.log([...range(-3)]);      // []
console.log([...range(-3, 0)]);   // [-3, -2, -1]
Run Code Online (Sandbox Code Playgroud)

它支持哪些可以比任何参数0stop并且可被递增step。与不超过数字的数字一起使用时,其行为与Python版本相同Number.MAX_SAFE_INTEGER

请注意以下情况:

[...range(0, 0, 0)];        // RangeError: range() step argument invalid
[...range(Number.MAX_SAFE_INTEGER + 1, Number.MAX_SAFE_INTEGER + 2)];  // []
[...range(Number.MAX_SAFE_INTEGER + 2, Number.MAX_SAFE_INTEGER + 3)];  // Infinite loop
[...range(0.7, 0.8, 0.1)];  // [0.7, 0.7999999999999999]
[...range('1', '11')];      // ['1']
[...range('2', '22')];      // Infinite loop
Run Code Online (Sandbox Code Playgroud)

@Tadeck@ Volv@ janka102的答案相反[]undefinedstep0or 求值时返回,或进入无限循环NaN,此生成器函数将引发类似于Python行为的异常。


Ili*_*asT 5

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

// Generate numbers range 0..4
console.log("range(0, 4, 1):", range(0, 4, 1));
// [0, 1, 2, 3, 4] 

// Generate numbers range 1..10 with step of 2 
console.log("\nrange(1, 10, 2):", range(1, 10, 2));
// [1, 3, 5, 7, 9]

// Generate the alphabet using Array.from making use of it being ordered as a sequence
console.log("\nrange('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x))", range('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x)));
// ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
Run Code Online (Sandbox Code Playgroud)