কেবলমাত্র ES2015 এ 0 থেকে n এর পরিসীমা কীভাবে উত্পন্ন করা যায়?


122

rangeঅজগর এবং অন্যদের মধ্যে জাভাস্ক্রিপ্ট থেকে পাওয়া ফাংশনটি সর্বদা খুঁজে পেয়েছি ? ES2015 এ সংখ্যার ব্যাপ্তি তৈরি করার কোনও সংক্ষিপ্ত উপায় আছে?

সম্পাদনা: আমার প্রশ্ন উল্লিখিত সদৃশ থেকে আলাদা কারণ এটি ES2015 এর সাথে নির্দিষ্ট এবং ECMAScriptT-5 নয়। এছাড়াও আমার 0 থেকে শুরু করার নির্দিষ্ট পরিসীমাটি নির্দিষ্ট করতে হবে না (যদিও এটি সেখানে থাকলে ভাল হবে)


উত্তরটি ES5 এবং ES6 এর জন্য একই।
লোগানফস্মিথ

1
তবে আপনি ES2015 তে সর্বদা কিছু নতুন ওগ ধারণা যেমন জেনারেটর, নতুন অ্যারে পদ্ধতি ইত্যাদি ব্যবহার করতে পারেন। এটি আপনাকে কার্য
আদিত্য সিং

7
আমি মনে করি @Delapouite নিখুঁত মধ্যে এই উত্তর আছে সদৃশ প্রশ্নের উত্তর মন্তব্য : [...Array(n).keys()]
jib


2
[...Array(5)].map((_,i) => i+1)
নিক indiessance

উত্তর:


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
এটি টাইপস্ক্রিপ্টে কাজ করে না কারণ কীগুলি () অ্যারের পরিবর্তে একটি অ্যারে আইট্রেটার ফেরত দেয়। আরও সার্বজনীন পদ্ধতির জন্য চেকআউট আদিত্য-সিংহের উত্তর।
ডেভিড ডোমিংগো

3
…… বা Array.from(Array(n).keys())
Ван

2
@ ডেভিডগনজালেজ শ্যানন আপনি কি জানেন [...Array(n).keys()]টাইপস্ক্রিপ্টে কাজ করে না কেন ? এটি অন্যান্য জেএস বাস্তবায়ন থেকে ইচ্ছাকৃত বিচ্যুতি?
স্টু কক্স

আরে @StuCox আমার কেন ধারণা নেই তবে এটি এটিতে স্থানান্তর করে Array(5).keys().slice()এবং স্লাইস অ্যারে পুনরুক্তি করার পদ্ধতি নয়। টাইপসক্রিপ্টআরং.আর.প্লে
ডেভিড ডোমিংগো

97

আমি আরও একটি স্বজ্ঞাত উপায় ব্যবহার করে খুঁজে পেয়েছি Array.from :

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

এখন এই rangeফাংশনটি 0 থেকে শুরু করে এন -1 পর্যন্ত সমস্ত নম্বর প্রদান করবে

সমর্থন করার জন্য পরিসীমাটির একটি পরিবর্তিত সংস্করণ startএবং endহ'ল:

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

সম্পাদনা @ মার্কো by এর পরামর্শ অনুসারে, এটি যদি আপনার ব্যবহারের ক্ষেত্রে উপযুক্ত হয় তবে আপনি এটি একটি স্থিতিশীল পদ্ধতি হিসাবে রাখতে পারেন

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)...
টাইপস্ক্রিপ্ট এতে

[ts] Property 'range' does not exist on type 'ArrayConstructor'। thouths?
কুনসেভিক.দেব 8:48 এ 818

ওভাররাইডিং বিল্ট-ইনগুলি এখন জাভাস্ক্রিপ্টে খারাপ অনুশীলন হিসাবে বিবেচিত হয়।
jhohlfeld

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.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

ধাপ ES6 সহ ব্যাপ্তি, যা অজগরটির মতো কাজ করে 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
প্রশ্নটা ভালো লাগলো! এটি আমার কৌণীয় 8 এইচটিএমএল * এনজিফোর্ড লুপ টেম্পলেটগুলিতে অনেক ক্লিনার কোড পেতে আমাকে সহায়তা করেছিল।
স্যাম

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()]টাইপস্ক্রিপ্টে কাজ করতে চায় তা জানাতে চাই।
পেইসং

3
তারপরে ব্যবহার করুন Array.from(Array(n).keys())। আমি নিশ্চিত যে এটি কাজ করা উচিত যদিও, স্প্রেড সিনট্যাক্স সহ আক্ষরিক কি স্থানান্তরিত করে?
বার্গি

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 আপনি বলতে পারেন পোস্ট করার আগে আমি সমস্ত বিদ্যমান উত্তর পড়িনি: - /
ডেভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.