JavaScript'te Python'a benzer bir işlev var range()mı?
Bence her seferinde aşağıdaki satırları yazmaktan daha iyi bir yol olmalı:
array = new Array();
for (i = 0; i < specified_len; i++) {
array[i] = i;
}
Yanıtlar:
Hayır , yok ama bir tane yapabilirsin .
range()Python'da nasıl çalıştığını taklit etmeye çalışırken, şuna benzer bir işlev yaratırdım:
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;
};
Bu jsfiddle'a bakın için .
range()JavaScript ve Python arasında karşılaştırmaŞu şekilde çalışır:
range(4)döner [0, 1, 2, 3],range(3,6)döner [3, 4, 5],range(0,10,2)döner [0, 2, 4, 6, 8],range(10,0,-1)döner [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],range(8,2,-2)döner [8, 6, 4],range(8,2)döner [],range(8,2,2)döner [],range(1,5,-1)döner [],range(1,5,-2)döner [],ve Python muadili tam olarak aynı şekilde çalışır (en azından belirtilen durumlarda):
>>> 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)
[]
Dolayısıyla, Python'a benzer şekilde çalışması için bir işleve ihtiyacınız varsa range(), yukarıda belirtilen çözümü kullanabilirsiniz.
stopdaha büyük olduğundan emin olun start(ve değilse onları değiştirin).
start >= stopHedef gerçekten Python'un menzilini taklit ediyorsa, boş bir diziye yönlendirmek gereklidir. Ve yine de daha sezgisel olduğunu iddia ediyorum.
start >= stopBu işlevin range()Python'daki gibi davranması için basit olması yeterli olmadığından , kontrol daha karmaşık olabilir . Cevabımı güncelledim.
ES6'da çok basit bir aralık için:
let range = n => Array.from(Array(n).keys())
Gönderen bigOmega yorumuyla , bu kullanarak kısaltılabilir Yayılması sözdizimi :
let range = n => [...Array(n).keys()]
let range = n => [...Array(n).keys()]
constolabildiğince çok kullanmaya çalışıyorum , ama burada sadece diziye bir referans olacak, bu yüzden dizi yine de düzenlenebilir olacak: 'D
constdönüş değeri değil, kendisi için geçerli olacaktır. Muhtemelen işlevi hiçbir şekilde değiştirmek istemezsiniz.
2018: Bu yanıt olumlu oylar almaya devam ediyor, işte bir güncelleme. Aşağıdaki kod eski, ancak neyse ki ES6 standartlaştırılmış oluşturucular ve yieldanahtar kelime ve bunlar evrensel olarak platformlar arasında destekleniyor. Tembel bir örneği range()kullanılarak yieldbulunabilir burada .
Daha önce söylenenlere ek olarak, Javascript 1.7+ yineleyiciler ve oluşturucular için destek sağlar ; bunlar, Python2'ye benzer range, tembel, bellek açısından verimli bir sürüm oluşturmak için kullanılabilir 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
stepargüman ve alınan değerler üzerinde test Cevabıma ? Cevabınız, aklımızda çok özel tarayıcıların olduğu uygulamalar için harika (Google Chrome, Safari ve 9'dan önceki IE sürümlerinde çalışmaz: stackoverflow.com/a/2209743/548696 ).
range"son" değeri hariç tutulmuştur (bu nedenle yukarıdaki kod >=yerine kullanılması gerekir >)
@Tadeck ve @georg'dan gelen iki yanıtı birleştirerek şunu buldum :
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;
}
}
Bir for döngüsünde kullanmak için ES6 / JS1.7 for-of döngüsüne ihtiyacınız vardır:
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
stepparametresi, ama ne zaman stop, hem de geçmedi startve stopihtiyaç değiştirilmesi. Güncelleyeceğim
Bir liman rangePython 2'den işlevi tarafından sağlanan underscore.js ve lodash (diğer pek çok yararlı araçlar ile birlikte) yardımcı kütüphaneleri. Alt çizgi belgelerinden kopyalanan örnekler:
_.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);
=> []
NumberPrototipe bir yineleyici eklenerek elde edilebilir
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'ın Rethinking Asynchronous JavaScript kursundan alınmıştır.
Aralığın hem başlangıç hem de bitiş konumunu belirtmeniz gerektiğinde yanıtlardan biri için küçük bir uzantı:
let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);
Hadi bakalım.
Bu, her bir dizinin değerini dizin numarasıyla yazar (veya üzerine yazar).
Array.prototype.writeIndices = function( n ) {
for( var i = 0; i < (n || this.length); ++i ) this[i] = i;
return this;
};
Bir sayı sağlamazsanız, Dizinin mevcut uzunluğunu kullanır.
Bunu şu şekilde kullanın:
var array = [].writeIndices(10); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Bir dizi boyut elde etmek için x, burada herhangi bir kitaplık kullanmadan tek satırlık bir program var
var range = n => Array(n + 1).join(1).split('').map((x, i) => i)
olarak çalışır
> range(4)
[0, 1, 2, 3]
var range = n => Array(n).fill().map((e, i) => i);
xaslında kullanılan' nparametre adı olarak
Aşağıda Python'un range () işlevinin JavaScript'e doğal bir uyarlaması verilmiştir :
// 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]
Bu mukayese edilebilir herhangi bir argüman destekler 0ve stopve ile artırılabilir step. Sayılarla kullanıldığında Python sürümüyle aynı şekilde davranır Number.MAX_SAFE_INTEGER.
Lütfen aşağıdaki köşe durumlarına dikkat edin:
[...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
Aksine @ Tadeck en , Volv en @ ve @ janka102 en cevabı hangi dönüş [], undefinedveya sonsuz bir döngüye girmek stepdeğerlendirir için 0veya NaNbu jeneratör işlevi Python'un davranışa benzer bir istisna atar.
ES6 varsayılan parametreleriyle daha da iyileştirildi.
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
}
pythonicPython rangedavranışını en iyi JS 'oluşturucuları ( yield) kullanarak taklit ederek hem range(stop)ve hem de range(start, stop, step)kullanım durumlarını destekler . Buna ek olarak, pythonic'nin rangeişlevi döndüren IteratorPython benzer nesneyi o destekler mapve filtertek tek gömlekleri gibi fantezi yapabileceğini böylece:
import {range} from 'pythonic';
// ...
const results = range(5).map(wouldBeInvokedFiveTimes);
// `results` is now an array containing elements from
// 5 calls to wouldBeInvokedFiveTimes
Şunları kullanarak kurun npm:
npm install --save pythonic
Açıklama Pythonic'in yazarı ve bakımcısıyım
MDN şu yaklaşımı önerir: Sıra oluşturucu (aralık)
// 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"]
JavaScript'te Python'un range () işlevine benzer bir işlev var mı?
Buradaki tüm çözümler Python 2'nin aralığına atıfta bulunuyor (muhtemelen verdiğiniz kod örneğinden dolayı). Ancak Python 3'te, range () yöntemi bir yineleyici döndürür. JavaScript ayrıca yineleyicilere sahiptir ve tüm diziyi oluşturup bellekte depolamaktan daha fazla alan verimlidir.
Yani Python 3'ün range(n)işlevinin daha doğru temsiliArray(n).keys() .
Örneğin:
for (let i of Array(n).keys()) {
console.log(i) // 0, 1, 2, 3, ..., n
}
Bir örnek daha (diğer cevaplarda zaten ele alınmıştır). Yineleyiciyi bir diziye dönüştürme (ES6):
let ary = [...Array(n).keys()];
// ary = [0, 1, 2, 3, ..., n]
Hala eşdeğer yerleşik bir işlev yok range(), ancak en son sürüm olan ES2015 ile kendi uygulamanızı oluşturabilirsiniz. İşte bunun sınırlı bir versiyonu. Sınırlıdır çünkü adım parametresini hesaba katmaz. Sadece min, maks.
const range = (min = null, max = null) =>
Array.from({length:max ? max - min : min}, (v,k) => max ? k + min : k)
Bu, Array.frombir lengthözelliği olan herhangi bir nesneden bir dizi oluşturabilen yöntem tarafından gerçekleştirilir . Dolayısıyla, sadece lengthözelliğe sahip basit bir nesnenin aktarılması, bir lengthdizi nesne verecek bir ArrayIterator yaratacaktır .
Bu benim tercih ettiğim yol. Python'daki gibi bir veya iki giriş belirlemenize izin verir.
function range(start, end) {
return Array.from(Array(end||start).keys()).slice(!!end*start)
}
İşte aralığın başka bir es6uygulaması
// 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}`)
}
-20için -30?
Hayır, yok ama bir tane yapabilirsin.
Aralığın Python3 davranışına kısmi. Aşağıda JavaScript'in Python'un aralığı () uygulamasını bulacaksınız:
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.
Tek adımda basit bir aralığa ihtiyacınız olduğunu varsayarsak:
let range = (start, end)=> {
if(start === end) return [start];
return [start, ...range(start + 1, end)];
}
Başka
let range = (start, end, step)=> {
if(start === end) return [start];
return [start, ...range(start + step, end)];
}
daha fazlası için buraya bakın .
JavaScript'te Python'un range () işlevine benzer bir işlev var mı?
Daha önce cevaplandığı gibi: hayır , yok. Ama kendinizinkini yapabilirsiniz. Bunun ES6 için ilginç bir yaklaşım olduğuna inanıyorum. Python 2.7'ye çok benzer şekilde çalışır range(), ancak çok daha dinamiktir.
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
}
Bu işlev üç farklı şekilde davranabilir (tıpkı Python'un range () gibi):
range(stop)range(start, stop)range(start, stop, step)Bu örnekler:
console.log(range(5))
console.log(range(-2, 2))
console.log(range(2, -2))
console.log(range(10, 20, 2))
Size aşağıdaki çıktıyı verecektir:
[ 0, 1, 2, 3, 4 ]
[ -2, -1, 0, 1, 2 ]
[ 2, 1, 0, -1, -2 ]
[ 10, 12, 14, 16, 18, 20 ]
inOperatörle (python gibi) dizi üzerinde yineleme yapmak yerine, kullanmanız gerektiğini unutmayın of. Böylece ideğişken, dizinin elemanının dizinini değil değerini varsayar.
for(let i of range(5))
{
// do something with i...
}
NodeJ'ler için bir seçenek, bir Buffer kullanmaktır:
[...Buffer.alloc(5).keys()]
// [ 0, 1, 2, 3, 4 ]
Güzel olan, doğrudan arabellekte yineleyebilmeniz:
Buffer.alloc(5).forEach((_, index) => console.log(index))
// 0
// 1
// 2
// 3
// 4
Bunu başlatılmamış bir Dizi ile yapamazsınız:
Array(5).forEach((_, index) => console.log(index))
// undefined
Ancak, aklı başında böyle bir amaç için Tampon kullanan;)
İşte bunu nasıl yaparım
let n = 5
[...Array(n).keys()].map(x=>{console.log(x)})
çıktı
0
1
2
3
4
range()Python'da çalışma şeklini taklit etmeyi amaçlayan bir işlev yazdım , böylece onu kullanabilirsiniz. JavaScript'te böyle bir işlev yoktur, ancakRangeMooTools için sınıf gibi farklı çerçeveler için bazı eklentiler vardır .