JavaScript中的函数是否类似于Python的range()
?
我认为应该有一个更好的方法,而不是每次写下面的行:
array = new Array();
for (i = 0; i < specified_len; i++) {
array[i] = i;
}
答案 0 :(得分:82)
对于ES6中非常简单的范围:
let range = n => Array.from(Array(n).keys())
答案 1 :(得分:70)
否,没有,但你可以制作一个。
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;
};
请参阅this jsfiddle以获取证明。
range()
的比较它的工作方式如下:
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)
[]
因此,如果您需要一个与Python的range()
类似的函数,您可以使用上述解决方案。
答案 2 :(得分:25)
2018:这个答案不断上升,所以这是一个更新。下面的代码已经过时,但幸运的是ES6标准化生成器和yield
关键字,它们在不同平台上得到普遍支持。可以找到使用range()
的惰性yield
的示例here。
除了已经说过的内容之外,Javascript 1.7+还提供对iterators and generators的支持,可用于创建range
的惰性,内存效率版本,在Python2中类似于xrange
:
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
答案 3 :(得分:16)
Python range
函数的端口由underscore.js和lodash实用程序库(以及许多其他有用的工具)提供。从下划线文档复制的示例:
_.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);
=> []
答案 4 :(得分:15)
将@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;
}
}
要在for循环中使用它,需要ES6 / JS1.7 for-of循环:
for (let i of range(0, 10, 2)) {
console.log(i);
}
// Outputs => 0 2 4 6 8
答案 5 :(得分: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]
取自Kyle Simpson的课程重新思考异步JavaScript
答案 6 :(得分:7)
你走了。
这将使用索引号写入(或覆盖)每个索引的值。
Array.prototype.writeIndices = function( n ) {
for( var i = 0; i < (n || this.length); ++i ) this[i] = i;
return this;
};
如果您不提供数字,它将使用数组的当前长度。
像这样使用:
var array = [].writeIndices(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
答案 7 :(得分:5)
如果你需要指定范围的起始位置和结束位置,这里是其中一个答案的小扩展名:
.index
答案 8 :(得分: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]
&#13;
它支持任何可以与0
和stop
进行比较的参数,并且可以增加step
。当与不超过Number.MAX_SAFE_INTEGER
的数字一起使用时,它的行为与Python版本相同。
请注意以下几个案例:
[...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
与@Tadeck's,@Volv's和@janka102's回答相反,回复[]
,undefined
或在step
评估时返回无限循环0
或NaN
,此生成器函数抛出类似于Python行为的异常。
答案 9 :(得分:4)
要获得大小为x
的数组,这里是一个不使用任何库的单行
var range = n => Array(n + 1).join(1).split('').map((x, i) => i)
作为
> range(4)
[0, 1, 2, 3]
答案 10 :(得分:3)
使用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
}
答案 11 :(得分:2)
您可以使用underscore库。它包含许多用于处理数组的有用函数。
答案 12 :(得分:1)
实际上,在 Python 中 range() 返回一个可迭代对象,我们知道迭代器比数组(或 Python 中的列表)的内存效率更高。 因此,如果我们想在 JavaScript 中实现具有精确功能的相同概念,我们可以使用迭代器对象:
class range {
constructor(start, stop, step = 1) {
//check for invalid input
if (stop !== undefined && typeof stop !== 'number'
|| typeof start !== 'number'
|| typeof step !== 'number') {
throw Error('invalid input for range function');
}
//check if second argument is provided
if (stop === undefined) {
stop = start;
start = 0;
}
//initialize the object properties
this.start = start;
this.stop = stop;
this.step = step;
}
//create the iterator object with Symbol.iterator
[Symbol.iterator]() {
return {
current: this.start,
last: this.stop,
step: this.step,
//implement the next() method of the iterator
next() {
if (this.step === 0) {
return { done: true };
} else if (this.step > 0 ? this.current < this.last : this.current > this.last) {
let value = this.current;
this.current += this.step;
return { done: false, value };
} else {
return { done: true };
}
}
};
};
}
例如我们有:
for (const num of new range(1, 10, 2)) {
console.log(num);
}
我们也可以很容易地创建一个数组:
let arr = [...new range(10, -5, -1)];
或:
let arr = Array.from(new range(10));
答案 13 :(得分:1)
这是我的首选方式。它允许您像在Python中那样指定一个或两个输入。
function range(start, end) {
return Array.from(Array(end||start).keys()).slice(!!end*start)
}
答案 14 :(得分:1)
JavaScript中是否有类似于Python的range()的函数?
这里所有的解决方案都指的是Python 2的范围(可能是由于您提供的代码示例)。但是在Python 3中,range()方法返回一个迭代器。 JavaScript还具有迭代器,并且迭代器比生成整个数组并将其存储在内存中更节省空间。
因此,Python 3的range(n)
函数的更准确表示是Array(n).keys()
。
例如:
for (let i of Array(n).keys()) {
console.log(i) // 0, 1, 2, 3, ..., n
}
另一个示例(其他答案中已经介绍过)。将迭代器转换为数组(ES6):
let ary = [...Array(n).keys()];
// ary = [0, 1, 2, 3, ..., n]
答案 15 :(得分:0)
递归函数是实现此类功能的最佳解决方案。
如果你只想得到从零开始的数字
function range(n) {
if (n > 0){
return [...range(n-1), n];
};
return [0];
};
console.log("range(5) => ", range(5));
例如
range(5) = [...range(4), 5]
= [...range(3), 4, 5]
= [...range(2), 3, 4, 5]
= [...range(1), 2, 3, 4, 5]
= [...range(0), 1, 2, 3, 4, 5] // range(0) = [0]
= [0, 1, 2, 3, 4, 5] //final answer
此功能还可以扩展如下
function range(start, stop, step=1){
if( stop > start){
return [...range(start, stop-step), stop];
}
return [start];
}
console.log("range(2, 8, 2) => ", range(2, 8, 2));
但请注意,与 Python 不同的是,您必须提供两个或三个参数。
答案 16 :(得分:0)
function range(start, stop) {
if (typeof stop == 'undefined') {
stop = start;
start = 0;
}
result = [...Array(stop).keys()].slice(start, stop);
return result;
}
答案 17 :(得分:0)
NodeJ的一个选项是使用缓冲区:
[...Buffer.alloc(5).keys()]
// [ 0, 1, 2, 3, 4 ]
很好的是,您可以直接在缓冲区上进行迭代:
Buffer.alloc(5).forEach((_, index) => console.log(index))
// 0
// 1
// 2
// 3
// 4
您不能使用未初始化的数组来做到这一点:
Array(5).forEach((_, index) => console.log(index))
// undefined
但是,谁在他们的右脑中使用Buffer这样的目的;)
答案 18 :(得分:0)
JavaScript中是否有类似于Python的range()的函数?
如之前回答:否,没有。但是你可以自己做。
我相信这对于ES6是一种有趣的方法。它的工作原理与Python 2.7 range()
非常相似,但它的动态性要强得多。
function range(start, stop, step = 1)
{
// This will make the function behave as range(stop)
if(arguments.length === 1)
{
return [...Array(arguments[0]).keys()]
}
// Adjusts step to go towards the stop value
if((start > stop && !(step < 0)) ||
(start < stop && !(step > 0)))
{
step *= -1
}
let returnArray = []
// Checks if i is in the interval between start and stop no matter if stop
// is lower than start or vice-versa
for(let i = start; (i-start)*(i-stop) <= 0; i += step)
{
returnArray.push(i)
}
return returnArray
}
此函数可以三种不同的方式运行(就像Python的range()一样):
range(stop)
range(start, stop)
range(start, stop, step)
这些示例:
console.log(range(5))
console.log(range(-2, 2))
console.log(range(2, -2))
console.log(range(10, 20, 2))
将为您提供以下输出:
[ 0, 1, 2, 3, 4 ]
[ -2, -1, 0, 1, 2 ]
[ 2, 1, 0, -1, -2 ]
[ 10, 12, 14, 16, 18, 20 ]
请注意,您不必使用in
来遍历数组,而必须使用of
。因此,i
变量采用数组元素的值而不是索引。
for(let i of range(5))
{
// do something with i...
}
答案 19 :(得分:0)
假设您需要一个简单的范围,只需一步即可:
let range = (start, end)=> {
if(start === end) return [start];
return [start, ...range(start + 1, end)];
}
其他
let range = (start, end, step)=> {
if(start === end) return [start];
return [start, ...range(start + step, end)];
}
请参阅here。
答案 20 :(得分:0)
不,没有,但是你可以制造一个。
我偏爱range3的Python3行为。您将在下面的JavaScript的Python range()实现中找到
:
function* range(start=0, end=undefined, step=1) {
if(arguments.length === 1) {end = start, start = 0}
[...arguments].forEach(arg => {
if( typeof arg !== 'number') {throw new TypeError("Invalid argument")}
})
if(arguments.length === 0) {throw new TypeError("More arguments neede")}
if(start >= end) return
yield start
yield* range(start + step, end, step)
}
// Use Cases
console.log([...range(5)])
console.log([...range(2, 5)])
console.log([...range(2, 5, 2)])
console.log([...range(2,3)])
// You can, of course, iterate through the range instance.
答案 21 :(得分:0)
MDN建议采用这种方法:Sequence generator (range)
答案 22 :(得分:0)
pythonic
使用JS'生成器(range
)最好地模仿Python yield
行为,同时支持range(stop)
和range(start, stop, step)
用例。此外,pythonic
的{{1}}函数会返回支持range
和Generator
的自定义构建的map
对象,因此可以执行以下内容:
filter
使用import {range} from 'pythonic';
// ...
const results = range(5).map(wouldBeInvokedFiveTimes);
// `results` is now an array containing elements from
// 5 calls to wouldBeInvokedFiveTimes
安装:
npm
以下是npm install --save pythonic
中范围:
pythonic
答案 23 :(得分:0)
以下是范围
的另一个es6
实现
// range :: (from, to, step?) -> [Number]
const range = (from, to, step = 1) => {
//swap values if necesery
[from, to] = from > to ? [to, from] : [from, to]
//create range array
return [...Array(Math.round((to - from) / step))]
.map((_, index) => {
const negative = from < 0 ? Math.abs(from) : 0
return index < negative ?
from + index * step :
(index - negative + 1) * step
})
}
range(-20, 0, 5)
.forEach(val => console.log(val))
for(const val of range(5, 1)){
console.log(`value ${val}`)
}
答案 24 :(得分:0)
仍然没有相当于range()
的内置函数,但是使用最新版本 - ES2015 - 您可以构建自己的实现。这是它的限量版本。有限,因为它没有考虑步骤参数。最小,最大
const range = (min = null, max = null) => Array.from({length:max ? max - min : min}, (v,k) => max ? k + min : k)
这是通过Array.from
方法实现的,该方法能够从具有length
属性的任何对象构建数组。因此传入一个只有length
属性的简单对象将创建一个ArrayIterator,它将产生length
个对象。
答案 25 :(得分:-1)
这是我的方法
let n = 5
[...Array(n).keys()].map(x=>{console.log(x)})
输出
0
1
2
3
4