Có một chức năng nào trong JavaScript tương tự như trong Python range()không?
Tôi nghĩ nên có một cách tốt hơn là mỗi lần viết những dòng sau:
array = new Array();
for (i = 0; i < specified_len; i++) {
array[i] = i;
}
Câu trả lời:
Không , không có, nhưng bạn có thể làm một cái .
range()Cố gắng mô phỏng cách nó hoạt động trong Python , tôi sẽ tạo hàm tương tự như sau:
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;
};
Xem jsfiddle này để biết bằng chứng.
range()JavaScript và PythonNó hoạt động theo cách sau:
range(4)trả lại [0, 1, 2, 3],range(3,6)trả lại [3, 4, 5],range(0,10,2)trả lại [0, 2, 4, 6, 8],range(10,0,-1)trả lại [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],range(8,2,-2)trả lại [8, 6, 4],range(8,2)trả lại [],range(8,2,2)trả lại [],range(1,5,-1)trả lại [],range(1,5,-2)trả lại [],và đối tác Python của nó hoạt động theo cùng một cách (ít nhất là trong các trường hợp đã đề cập):
>>> 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)
[]
Vì vậy, nếu bạn cần một hàm hoạt động tương tự như Python range(), bạn có thể sử dụng giải pháp đã đề cập ở trên.
stoplớn hơn start(và hoán đổi chúng nếu không).
start >= stopdẫn đến một mảng trống là cần thiết nếu mục tiêu thực sự là mô phỏng phạm vi của Python. Và tôi cho rằng nó trực quan hơn dù sao.
start >= stoplà không đủ để hàm này hoạt động như range()trong Python. Tôi đã cập nhật câu trả lời của mình.
Đối với một phạm vi rất đơn giản trong ES6:
let range = n => Array.from(Array(n).keys())
Từ bình luận của bigOmega , điều này có thể được rút ngắn bằng cú pháp Spread :
let range = n => [...Array(n).keys()]
let range = n => [...Array(n).keys()]
constcàng nhiều càng tốt, nhưng ở đây nó sẽ chỉ là một tham chiếu đến mảng, vì vậy mảng sẽ vẫn có thể chỉnh sửa: 'D
constsẽ áp dụng cho chính hàm, không phải giá trị trả về của nó. Bạn có thể không muốn sửa đổi chức năng theo bất kỳ cách nào.
2018: câu trả lời này tiếp tục nhận được sự ủng hộ, vì vậy đây là bản cập nhật. Mã bên dưới đã lỗi thời, nhưng may mắn thay, các trình tạo và yieldtừ khóa được chuẩn hóa ES6 , và chúng được hỗ trợ phổ biến trên các nền tảng. Ví dụ về lười range()sử dụng yieldcó thể được tìm thấy ở đây .
Ngoài những gì đã nói, Javascript 1.7+ cung cấp hỗ trợ cho các trình lặp và trình tạo có thể được sử dụng để tạo phiên bản lười biếng, tiết kiệm bộ nhớ range, xrangemô phỏng trong 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
stepđối số và kiểm tra nó trên các giá trị từ câu trả lời của tôi không? Câu trả lời của bạn là tuyệt vời cho các ứng dụng mà chúng tôi có các trình duyệt rất cụ thể (nó sẽ không hoạt động trong Google Chrome, Safari và IE phiên bản cũ hơn 9: stackoverflow.com/a/2209743/548696 ).
rangecó giá trị "cuối cùng" bị loại trừ (vì vậy người ta cần sử dụng >=thay vì >trong mã trên)
Kết hợp cả hai câu trả lời từ @Tadeck và @georg lại với nhau , tôi đã nghĩ ra điều này:
function* range(start, stop, step = 1) {
if (stop == null) {
// one param defined
stop = start;
start = 0;
}
for (let i = start; step > 0 ? i < stop : i > stop; i += step) {
yield i;
}
}
Để sử dụng nó trong vòng lặp for, bạn cần vòng lặp for-of-ES6 / JS1.7:
for (let i of range(5)) {
console.log(i);
}
// Outputs => 0 1 2 3 4
for (let i of range(0, 10, 2)) {
console.log(i);
}
// Outputs => 0 2 4 6 8
for (let i of range(10, 0, -2)) {
console.log(i);
}
// Outputs => 10 8 6 4 2
steptham số, nhưng khi stopkhông được truyền vào, cả hai startvà stopcần được thay đổi. Tôi sẽ cập nhật nó
Một cổng của rangehàm từ Python 2 được cung cấp bởi các thư viện tiện ích underscore.js và lodash (cùng với nhiều công cụ hữu ích khác). Ví dụ được sao chép từ tài liệu gạch dưới:
_.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);
=> []
Có thể đạt được bằng cách gắn một trình lặp vào Numbernguyên mẫu
Number.prototype[Symbol.iterator] = function* () {
for (var i = 0; i <= this; i++) {
yield i
}
}
[...5] // will result in [0,1,2,3,4,5]
Lấy từ khóa học Kyle Simpson's Rethinking Asynchronous JavaScript
Đây là phần mở rộng nhỏ cho một trong các câu trả lời trong trường hợp bạn cần chỉ định cả vị trí bắt đầu và kết thúc của dải ô:
let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);
Của bạn đây.
Thao tác này sẽ ghi (hoặc ghi đè) giá trị của mỗi chỉ mục bằng số chỉ mục.
Array.prototype.writeIndices = function( n ) {
for( var i = 0; i < (n || this.length); ++i ) this[i] = i;
return this;
};
Nếu bạn không cung cấp một số, nó sẽ sử dụng độ dài hiện tại của Mảng.
Sử dụng nó như thế này:
var array = [].writeIndices(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Để có được một mảng kích thước x, đây là một lớp lót mà không cần sử dụng bất kỳ thư viện nào
var range = n => Array(n + 1).join(1).split('').map((x, i) => i)
hoạt động như
> range(4)
[0, 1, 2, 3]
var range = n => Array(n).fill().map((e, i) => i);
x' khi bạn thực sự sử dụng nnhư tên tham số
Sau đây là sự điều chỉnh tự nhiên của hàm range () của Python sang 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]
Nó hỗ trợ bất kỳ đối số nào có thể được so sánh với 0và stopvà có thể được tăng dần bởi step. Nó hoạt động giống với phiên bản Python khi được sử dụng với số lượng không vượt quá Number.MAX_SAFE_INTEGER.
Xin lưu ý các trường hợp góc sau:
[...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
Ngược lại với @ Tadeck của , @ của Volv và @ janka102 của câu trả lời mà quay trở lại [], undefinedhoặc nhập một vòng lặp vô hạn khi stepđánh giá lại để 0hay NaN, chức năng máy phát điện này ném một ngoại lệ tương tự như hành vi của Python.
Tinh chỉnh thêm với các thông số mặc định của 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
}
pythonicbắt chước rangehành vi Python tốt nhất mà nó có thể sử dụng trình tạo JS '( yield), hỗ trợ cả trường hợp sử dụng range(stop)và range(start, stop, step)trường hợp. Bên cạnh đó, pythonic's rangehàm trả về một Iteratorđối tượng tương tự như Python hỗ trợ mapvà filter, vì vậy người ta có thể làm ưa thích một lớp lót như:
import {range} from 'pythonic';
// ...
const results = range(5).map(wouldBeInvokedFiveTimes);
// `results` is now an array containing elements from
// 5 calls to wouldBeInvokedFiveTimes
Cài đặt bằng npm:
npm install --save pythonic
Tiết lộ tôi là tác giả và người duy trì Pythonic
MDN khuyến nghị cách tiếp cận này: Trình tạo chuỗi (phạm vi)
// 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"]
Có một hàm trong JavaScript tương tự như phạm vi () của Python không?
Tất cả các giải pháp ở đây đều đề cập đến phạm vi của Python 2 (có thể do ví dụ mã bạn đã đưa ra). Tuy nhiên trong Python 3, phương thức range () trả về một trình lặp. JavaScript cũng có các trình vòng lặp và chúng hiệu quả hơn về không gian so với việc tạo toàn bộ mảng và lưu trữ nó trong bộ nhớ.
Vì vậy, các đại diện chính xác hơn về Python 3 của range(n)chức năng là Array(n).keys().
Ví dụ:
for (let i of Array(n).keys()) {
console.log(i) // 0, 1, 2, 3, ..., n
}
Một ví dụ khác (đã được đề cập trong các câu trả lời khác). Chuyển đổi trình lặp thành một mảng (ES6):
let ary = [...Array(n).keys()];
// ary = [0, 1, 2, 3, ..., n]
Vẫn không có chức năng tích hợp nào tương đương range(), nhưng với phiên bản mới nhất - ES2015 - bạn có thể xây dựng triển khai của riêng mình. Đây là một phiên bản giới hạn của nó. Hạn chế vì nó không tính đến tham số bước. Chỉ tối thiểu, tối đa.
const range = (min = null, max = null) =>
Array.from({length:max ? max - min : min}, (v,k) => max ? k + min : k)
Điều này được thực hiện bằng Array.fromphương pháp có thể xây dựng một mảng từ bất kỳ đối tượng nào có thuộc lengthtính. Vì vậy, việc truyền vào một đối tượng đơn giản chỉ với thuộc lengthtính sẽ tạo ra một ArrayIterator sẽ mang lại lengthsố lượng đối tượng.
Đây là cách ưa thích của tôi. Nó cho phép bạn chỉ định một hoặc hai đầu vào như trong Python.
function range(start, end) {
return Array.from(Array(end||start).keys()).slice(!!end*start)
}
Đây là một es6triển khai khác của phạm vi
// 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}`)
}
-20to -30?
Không, không có, nhưng bạn có thể làm một cái.
Tôi là một phần của hành vi Python3 của phạm vi. Bạn sẽ tìm thấy bên dưới việc triển khai phạm vi của Python () của JavaScript:
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.
Giả sử bạn cần một phạm vi đơn giản với một bước duy nhất:
let range = (start, end)=> {
if(start === end) return [start];
return [start, ...range(start + 1, end)];
}
khác
let range = (start, end, step)=> {
if(start === end) return [start];
return [start, ...range(start + step, end)];
}
tham khảo thêm tại đây .
Có một hàm trong JavaScript tương tự như phạm vi () của Python không?
Như đã trả lời trước đây: không , không có. Nhưng bạn có thể tự làm. Tôi tin rằng đây là một cách tiếp cận thú vị cho ES6. Nó hoạt động rất giống với Python 2.7 range(), nhưng năng động hơn nhiều.
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
}
Hàm này có thể hoạt động theo ba cách khác nhau (giống như phạm vi ()) của Python:
range(stop)range(start, stop)range(start, stop, step)Những ví dụ sau:
console.log(range(5))
console.log(range(-2, 2))
console.log(range(2, -2))
console.log(range(10, 20, 2))
Sẽ cung cấp cho bạn kết quả sau:
[ 0, 1, 2, 3, 4 ]
[ -2, -1, 0, 1, 2 ]
[ 2, 1, 0, -1, -2 ]
[ 10, 12, 14, 16, 18, 20 ]
Lưu ý rằng thay vì lặp lại mảng bằng intoán tử (như python), bạn phải sử dụng of. Do đó, ibiến giả định giá trị chứ không phải chỉ số của phần tử của mảng.
for(let i of range(5))
{
// do something with i...
}
Một tùy chọn cho NodeJs là sử dụng Buffer:
[...Buffer.alloc(5).keys()]
// [ 0, 1, 2, 3, 4 ]
Điều thú vị là bạn có thể lặp lại trực tiếp trên bộ đệm:
Buffer.alloc(5).forEach((_, index) => console.log(index))
// 0
// 1
// 2
// 3
// 4
Bạn không thể làm điều đó với Mảng chưa khởi tạo:
Array(5).forEach((_, index) => console.log(index))
// undefined
Nhưng, những người có suy nghĩ đúng đắn của họ sử dụng Bộ đệm cho mục đích như thế này;)
Đây là cách tôi làm điều đó
let n = 5
[...Array(n).keys()].map(x=>{console.log(x)})
đầu ra
0
1
2
3
4
range()hoạt động trong Python, vì vậy bạn có thể sử dụng nó. Không có chức năng này trong JavaScript, nhưng có một số plugin cho các khung công tác khác nhau, chẳng hạn nhưRangelớp cho MooTools .