ES2015 में 0 से n तक की संख्या कैसे उत्पन्न करें?


122

मैंने हमेशा rangeफ़ंक्शन को जावास्क्रिप्ट से गायब पाया है क्योंकि यह अजगर और अन्य में उपलब्ध है? ES2015 में संख्याओं की श्रेणी उत्पन्न करने का कोई संक्षिप्त तरीका है?

EDIT: मेरा प्रश्न उल्लेखित डुप्लिकेट से अलग है क्योंकि यह ES2015 के लिए विशिष्ट है न कि ECMASCRIPT-5 से। इसके अलावा, मुझे 0 से शुरू होने वाली सीमा की आवश्यकता है और विशिष्ट आरंभिक संख्या नहीं है (हालांकि अगर यह है तो अच्छा होगा)


उत्तर ES5 और ES6 के लिए समान है।
loganfsmyth

1
लेकिन आप हमेशा कुछ ऑग का उपयोग कर सकते हैं जैसे कि नई अवधारणाएं जैसे कि ईएस2015 में जनरेटर, नई एरे विधि आदि। इससे आपको कार्य को प्राप्त करने के लिए अतिरिक्त उपकरण
आदित्य सिंह

7
मुझे लगता है कि @Delapouite सही में इसका जवाब है डुप्लिकेट किए गए प्रश्न का उत्तर करने के लिए टिप्पणी : [...Array(n).keys()]
जिब


2
[...Array(5)].map((_,i) => i+1)
नीचता

जवाबों:


243

आप एक नए बनाए गए सरणी की कुंजियों पर स्प्रेड ऑपरेटर का उपयोग कर सकते हैं।

[...Array(n).keys()]

या

Array.from(Array(n).keys())

Array.from()यदि टाइपप्रति के साथ काम करने के लिए आवश्यक है वाक्य रचना


38
मीठा:function range (start, end) { return [...Array(1+end-start).keys()].map(v => start+v) }
शंकु

2
यह टाइपस्क्रिप्ट में काम नहीं करता है क्योंकि चाबियाँ () एक सरणी के बजाय एक सरणी Iterator लौटाती हैं। अधिक सार्वभौमिक दृष्टिकोण के लिए चेकआउट आदित्य-सिंह का जवाब।
डेविड डोमिंगो

3
…… या Array.from(Array(n).keys())
Константин Ван

2
@DavidGonzalezShannon क्या आप जानते हैं कि [...Array(n).keys()]टाइपस्क्रिप्ट में काम क्यों नहीं किया जाता है? क्या यह अन्य जेएस कार्यान्वयन से एक जानबूझकर विचलन है?
स्टु कॉक्स

अरे @StuCox मुझे पता नहीं क्यों लेकिन यह करने के लिए यह transpiles Array(5).keys().slice()और टुकड़ा it itter की विधि नहीं है। यहाँ पर इसका एक प्रकार है, जिसमें टाइपस्क्रिप्टब्लंग.org
डेविड डोमिंगो

98

मैंने एक और सहज तरीका भी पाया Array.from:

const range = n => Array.from({length: n}, (value, key) => key)

अब यह rangeफ़ंक्शन 0 से n-1 तक के सभी नंबरों को लौटा देगा

समर्थन करने के लिए सीमा का एक संशोधित संस्करण है startऔर endहै:

const range = (start, end) => Array.from({length: (end - start)}, (v, k) => k + start);

EDIT जैसा कि @ marco6 द्वारा सुझाया गया है, आप इसे एक स्थिर विधि के रूप में रख सकते हैं यदि यह आपके उपयोग के मामले के अनुकूल हो

Array.range = (start, end) => Array.from({length: (end - start)}, (v, k) => k + start);

और इसका उपयोग करें

Array.range(3, 9)

1
अच्छा है! हम इसके साथ ऐरे स्टैटिक इंटरफ़ेस का विस्तार क्यों नहीं करते? टाइपस्क्रिप्ट के साथ महान काम करता है: interface ArrayConstructor { range(n: number): number[]; } Array.range = n => Array.from({length: n}, (value, key) => key); और फिर हर जगहArray.range(x)...
marco6

[ts] Property 'range' does not exist on type 'ArrayConstructor'। thouths?
कुंसविक.देव

1
अंतर्निहित जावास्क्रिप्ट को अब जावास्क्रिप्ट में खराब अभ्यास माना जाता है।
जोहलफेल्ड

16

डेल्टा के साथ

जावास्क्रिप्ट के लिए

Array.from(Array(10).keys()).map(i => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]

[...Array(10).keys()].map(i => 4 + i * -2);
//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]

Array(10).fill(0).map((v, i) => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]

Array(10).fill().map((v, i) => 4 + i * -2);
//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]

[...Array(10)].map((v, i) => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]

const range = (from, to, step) =>
  Array(~~((to - from) / step) + 1) // '~~' is Alternative for Math.floor()
  .fill().map((v, i) => from + i * step);

range(0, 9, 2);
//=> [0, 2, 4, 6, 8]

Array.range = (from, to, step) => Array.from({
    length: ~~((to - from) / step) + 1
  },
  (v, k) => from + k * step
);

Array.range = (from, to, step) => [...Array(~~((to - from) / step) + 1)].map(
  (v, k) => from + k * step
)
Array.range(2, 10, 2);
//=> [2, 4, 6, 8, 10]

Array.range(0, 10, 1);
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Array.range(2, 10, -1);
//=> []

Array.range(3, 0, -1);
//=> [3, 2, 1, 0]


class Range {
  constructor(total = 0, step = 1, from = 0) {
    this[Symbol.iterator] = function*() {
      for (let i = 0; i < total; yield from + i++ * step) {}
    };
  }
}

[...new Range(5)]; // Five Elements
//=> [0, 1, 2, 3, 4]
[...new Range(5, 2)]; // Five Elements With Step 2
//=> [0, 2, 4, 6, 8]
[...new Range(5, -2, 10)]; // Five Elements With Step -2 From 10
//=>[10, 8, 6, 4, 2]
[...new Range(5, -2, -10)]; // Five Elements With Step -2 From -10
//=> [-10, -12, -14, -16, -18]

// Also works with for..of loop
for (i of new Range(5, -2, 10)) console.log(i);
// 10 8 6 4 2

// Or
const Range = function*(total = 0, step = 1, from = 0){
  for (let i = 0; i < total; yield from + i++ * step) {}
};

Array.from(Range(5, -2, -10));
//=> [-10, -12, -14, -16, -18]
[...Range(5, -2, -10)]; // Five Elements With Step -2 From -10
//=> [-10, -12, -14, -16, -18]

// Also works with for..of loop
for (i of Range(5, -2, 10)) console.log(i);
// 10 8 6 4 2

class Range2 {
  constructor(to = 0, step = 1, from = 0) {
    this[Symbol.iterator] = function*() {
      let i = 0,
        length = ~~((to - from) / step) + 1;
      while (i < length) yield from + i++ * step;
    };
  }
}
[...new Range2(5)]; // First 5 Whole Numbers
//=> [0, 1, 2, 3, 4, 5]

[...new Range2(5, 2)]; // From 0 to 5 with step 2
//=> [0, 2, 4]

[...new Range2(5, -2, 10)]; // From 10 to 5 with step -2
//=> [10, 8, 6]

// Or 
const Range2 = function*(to = 0, step = 1, from = 0) {
    let i = 0, length = ~~((to - from) / step) + 1;
    while (i < length) yield from + i++ * step;
};


[...Range2(5, -2, 10)]; // From 10 to 5 with step -2
//=> [10, 8, 6]

let even4to10 = Range2(10, 2, 4);
even4to10.next().value
//=> 4
even4to10.next().value
//=> 6
even4to10.next().value
//=> 8
even4to10.next().value
//=> 10
even4to10.next().value
//=> undefined

टाइपस्क्रिप्ट के लिए

interface _Iterable extends Iterable < {} > {
  length: number;
}

class _Array < T > extends Array < T > {
  static range(from: number, to: number, step: number): number[] {
    return Array.from(
      ( < _Iterable > { length: Math.floor((to - from) / step) + 1 }),
      (v, k) => from + k * step
    );
  }
}
_Array.range(0, 9, 1);
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

अपडेट करें

class _Array<T> extends Array<T> {
    static range(from: number, to: number, step: number): number[] {
        return [...Array(~~((to - from) / step) + 1)].map(
            (v, k) => from + k * step
        );
    }
}
_Array.range(0, 9, 1);

संपादित करें

class _Array<T> extends Array<T> {
    static range(from: number, to: number, step: number): number[] {
        return Array.from(Array(~~((to - from) / step) + 1)).map(
            (v, k) => from + k * step
        );
    }
}
_Array.range(0, 9, 1);

आपका अपडेट किया गया टाइपस्क्रिप्ट संस्करण काम नहीं करता है। यह संकेतित आकार के साथ एक खाली सरणी बनाता है। आपको टाइपस्क्रिप्ट के साथ Array.keys के साथ Array.from का उपयोग करने की आवश्यकता है। Array.from(Array(~~((to - from) / step) + 1).keys())
डेविड डोमिंगो


10

इनमें से बहुत सारे समाधान वास्तविक एरे वस्तुओं को त्वरित रूप से निर्मित करते हैं, जो बहुत सारे मामलों के लिए काम कर सकते हैं, लेकिन जैसे मामलों का समर्थन नहीं कर सकते हैं range(Infinity)। आप इन समस्याओं से बचने और अनंत दृश्यों का समर्थन करने के लिए एक साधारण जनरेटर का उपयोग कर सकते हैं:

function* range( start, end, step = 1 ){
  if( end === undefined ) [end, start] = [start, 0];
  for( let n = start; n < end; n += step ) yield n;
}

उदाहरण:

Array.from(range(10));     // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Array.from(range(10, 20)); // [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ]

i = range(10, Infinity);
i.next(); // { value: 10, done: false }
i.next(); // { value: 11, done: false }
i.next(); // { value: 12, done: false }
i.next(); // { value: 13, done: false }
i.next(); // { value: 14, done: false }

8

इसलिए, इस मामले में, यह अच्छा होगा यदि नंबर ऑब्जेक्ट प्रसार ऑपरेटर के साथ एक सरणी ऑब्जेक्ट की तरह व्यवहार करेगा।

उदाहरण के लिए , प्रसार ऑपरेटर के साथ प्रयोग की जाने वाली सरणी वस्तु:

let foo = [0,1,2,3];
console.log(...foo) // returns 0 1 2 3

यह इस तरह से काम करता है क्योंकि एरे ऑब्जेक्ट में एक अंतर्निर्मित पुनरावृत्ति है।
हमारे मामले में, हमें एक समान कार्यक्षमता के लिए नंबर ऑब्जेक्ट की आवश्यकता है :

[...3] //should return [0,1,2,3]

ऐसा करने के लिए हम बस उस उद्देश्य के लिए संख्या पुनरावृत्त बना सकते हैं।

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

अब प्रसार ऑपरेटर के साथ 0 से N तक की रेंज बनाना संभव है।

[... एन] // अब रिटर्न 0 ... एन सरणी

http://jsfiddle.net/01e4xdv5/4/

चीयर्स।


3

आप एक जनरेटर फ़ंक्शन का उपयोग कर सकते हैं, जो केवल आवश्यकता होने पर सीमा को आलसी बनाता है:

function* range(x, y) {
  while (true) {
    if (x <= y)
      yield x++;

    else
      return null;
  }
}

const infiniteRange = x =>
  range(x, Infinity);
  
console.log(
  Array.from(range(1, 10)) // [1,2,3,4,5,6,7,8,9,10]
);

console.log(
  infiniteRange(1000000).next()
);

आप जनरेटर पर नक्शा करने के लिए एक उच्च क्रम जनरेटर फ़ंक्शन का उपयोग कर सकते हैं range:

function* range(x, y) {
  while (true) {
    if (x <= y)
      yield x++;

    else
      return null;
  }
}

const genMap = f => gx => function* (...args) {
  for (const x of gx(...args))
    yield f(x);
};

const dbl = n => n * 2;

console.log(
  Array.from(
    genMap(dbl) (range) (1, 10)) // [2,4,6,8,10,12,14,16,18,20]
);

यदि आप निडर हैं, तो आप बहुत व्यापक रेंज (उद्देश्य के लिए) को संबोधित करने के लिए जनरेटर के दृष्टिकोण को भी सामान्य कर सकते हैं:

const rangeBy = (p, f) => function* rangeBy(x) {
  while (true) {
    if (p(x)) {
      yield x;
      x = f(x);
    }

    else
      return null;
  }
};

const lte = y => x => x <= y;

const inc = n => n + 1;

const dbl = n => n * 2;

console.log(
  Array.from(rangeBy(lte(10), inc) (1)) // [1,2,3,4,5,6,7,8,9,10]
);

console.log(
  Array.from(rangeBy(lte(256), dbl) (2)) // [2,4,8,16,32,64,128,256]
);

ध्यान रखें कि जनरेटर / पुनरावृत्तियाँ स्वाभाविक रूप से स्टेटफुल हैं, अर्थात् प्रत्येक आह्वान के साथ अंतर्निहित स्थिति में परिवर्तन होता है next। राज्य एक मिश्रित आशीर्वाद है।


3

चरण ईएस 6 के साथ रेंज, जो अजगर के समान काम करता है list(range(start, stop[, step])):

const range = (start, stop, step = 1) => {
  return [...Array(stop - start).keys()]
    .filter(i => !(i % Math.round(step)))
    .map(v => start + v)
}

उदाहरण:

range(0, 8) // [0, 1, 2, 3, 4, 5, 6, 7]
range(4, 9) // [4, 5, 6, 7, 8]
range(4, 9, 2) // [4, 6, 8] 
range(4, 9, 3) // [4, 7]

1
सवाल में अच्छा जोड़! इससे मुझे अपने Angular 8 html * ngFor लूप टेम्प्लेट में बहुत क्लीनर कोड प्राप्त करने में मदद मिली।
सैम

2

डेल्टा का समर्थन करने के लिए

const range = (start, end, delta) => {
  return Array.from(
    {length: (end - start) / delta}, (v, k) => (k * delta) + start
  )
};

1

आप इसे एक लाइनर के साथ भी कर सकते हैं जैसे कि यह एक स्टेप सपोर्ट के साथ:

((from, to, step) => ((add, arr, v) => add(arr, v, add))((arr, v, add) => v < to ? add(arr.concat([v]), v + step, add) : arr, [], from))(0, 10, 1)

परिणाम है [0, 1, 2, 3, 4, 5, 6 ,7 ,8 ,9]


2
क्या यह वाई-कॉम्बिनेटर है?
चेतन

1
यह वाई-कॉम्बिनेटर के विचार का अनुसरण करता है।
मार्सिन क्राल

1

यह फ़ंक्शन पूर्णांक अनुक्रम लौटाएगा।

const integerRange = (start, end, n = start, arr = []) =>
  (n === end) ? [...arr, n]
    : integerRange(start, end, start < end ? n + 1 : n - 1, [...arr, n]);

$> integerRange(1, 1)
<- Array [ 1 ]

$> integerRange(1, 3)
<- Array(3) [ 1, 2, 3 ]

$> integerRange(3, -3)
<- Array(7) [ 3, 2, 1, 0, -1, -2, -3 ]

0
const keys = Array(n).keys();
[...Array.from(keys)].forEach(callback);

टाइपस्क्रिप्ट में


दोनों का उपयोग करने Array.fromऔर वाक्यविन्यास को फैलाने का कोई कारण नहीं है । और फिर यह मौजूदा उत्तर के समान ही है।
बरगी

बस [...Array(n).keys()]टाइप प्वाइंट में काम नहीं करना चाहता ।
PeeSong

3
फिर उपयोग करें Array.from(Array(n).keys())। मुझे पूरा यकीन है कि हालांकि यह काम करना चाहिए, क्या शाब्दिक फैल सिंटैक्स ट्रांसपाइल के साथ है?
Bergi

0

यहाँ एक और भिन्नता है जो उपयोग नहीं करता है Array

let range = (n, l=[], delta=1) => {
  if (n < 0) { 
    return l 
  }
  else {
    l.unshift(n)
    return range(n - delta, l) 
  }
}

0

जनरेटर अब आपको बड़ी संख्या के लिए लेज़ीली और कम मेमोरी का उपयोग करके संख्या अनुक्रम उत्पन्न करने की अनुमति देते हैं।

हालांकि सवाल विशेष रूप से ES2015 में कहा गया है, मुझे उम्मीद है कि बहुत सारे टाइपस्क्रिप्ट उपयोगकर्ता यहां समाप्त हो जाएंगे और ईएस में रूपांतरण सीधा है ...

function range(end: number): IterableIterator<number>;
// tslint:disable-next-line:unified-signatures
function range(begin: number, end: number): IterableIterator<number>;

function *range(begin: number, end: number = NaN): IterableIterator<number> {
    let num = 0;
    if (isNaN(end)) {
        end = begin;
    } else {
        num = begin;
    }
    while (num < end) {
        yield num++;
    }
}

पहले दो फ़ंक्शन घोषणाएं सिर्फ आपके आईडीई में अधिक जानकारीपूर्ण समापन सुझाव प्रदान करने के लिए हैं।


Aaaaand आप बता सकते हैं कि मैंने पोस्ट करने से पहले सभी मौजूदा उत्तरों को नहीं पढ़ा: - /
डेव

0

कैसे सिर्फ मैपिंग के बारे में…।

Array (n) .map ((value, index) ....) वहाँ के रास्ते का 80% है। लेकिन किसी विषम कारण से यह काम नहीं करता है। लेकिन एक वर्कअराउंड है।

Array(n).map((v,i) => i) // does not work
Array(n).fill().map((v,i) => i) // does dork

एक सीमा के लिए

Array(end-start+1).fill().map((v,i) => i + start) // gives you a range

अजीब, ये दो पुनरावृत्तियाँ एक ही परिणाम लौटाती हैं: Array(end-start+1).entries()औरArray(end-start+1).fill().entries()

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.