最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ES67 equivalent to underscore’s range function - Stack Overflow

programmeradmin3浏览0评论

Is there any ECMAScript 6/7 equivalent to underscore’s range function?

In underscore:

_.range(startPage, endPage + 1);

In ES2015:

Array.from(Array(n), (_, i) => x + i)

Not sure how the ES2015 version works. I would like to know how range in ecmascript of javascript works

Is there any ECMAScript 6/7 equivalent to underscore’s range function?

In underscore:

_.range(startPage, endPage + 1);

In ES2015:

Array.from(Array(n), (_, i) => x + i)

Not sure how the ES2015 version works. I would like to know how range in ecmascript of javascript works

Share Improve this question edited Nov 8, 2017 at 21:35 Karty asked Nov 8, 2017 at 21:30 KartyKarty 1,3996 gold badges21 silver badges32 bronze badges 2
  • 1 What exactly is your question here? Are you looking for an ES6 version of range? Are you asking for clarification on how the second snippet works? If so, what precisely do you not understand about it? At least try to make an attempt at explaining it yourself. – Sebastian Simon Commented Nov 8, 2017 at 21:33
  • I would like to know how range in ecmascript of javascript works – Karty Commented Nov 8, 2017 at 21:35
Add a ment  | 

3 Answers 3

Reset to default 14

The idea is to create an array of length end - start + 1, and then fill it with the relevant numbers using Array#from.

The Array.from() method creates a new Array instance from an array-like or iterable object.

In this case Array#from needs an object with the length property. Using Array(n) creates such an object (array). You can also use { length: n } directly. In this case n = Math.abs(end - start) + 1.

Array#from accepts a mapFn callback, a function that can transform the iterated value. The function receives 2 params - the values (which we can ignore in this case), and the index (0 based). Adding start to the current index will create the numbers in the range.

const range = (start, end) => Array.from(
  Array(Math.abs(end - start) + 1), 
  (_, i) => start + i
);

console.log(range(5, 10));
console.log(range(-10, -5));
console.log(range(-5, 10));

This version will handle reverse range as well (large to small) as well:

const range = (start, end) => {
  const inc = (end - start) / Math.abs(end - start);
  
  return Array.from(
    Array(Math.abs(end - start) + 1), 
    (_, i) => start + i * inc
  );
};

console.log(range(5, 10));
console.log(range(-5, -10));
console.log(range(10, -5));

Note that the following implementation does not allow for lazy-generated lists:

Array.from(Array(n), (_, i) => x + i)

Imagine that you need a list of 1M numbers:

range(1, 1000000);

Are you going to consume all of them? Maybe not, yet all the numbers have been generated already and they probably left a non-trivial footprint on your memory.

It would be nice if we could get them one by one on demand.

It turns out we can do exactly that with a generator:

function* range(start, end, step = 1) {
  for (let value = start; value < end; value += step) {
    yield value;
  }
}

for (let x of range(1, Infinity)) {
  if (x > 10) {
    break;
  }
  console.log(x);
}

Did you notice the range(1, Infinity) bit?

In a classic implementation where all the numbers are generated in advance, this code wouldn't even run as you would get stuck in an infinite number-generating loop.

As I understand it, the range method generates an array of numbers starting from start, stepping with step (default = 1) until end. This simple function does just that :-)

const range = (start, end, step = 1) => {
  let result = [];
  for(let i=0; i<=end; i+=step) {
    result.push(i);
  }
  return result;
};

What is nice here is that you can use decimal step values.

For example:

range(0, 2, 0.5) // [ 0, 0.5, 1, 1.5, 2 ]
range(0,100,20) // [ 0, 20, 40, 60, 80, 100 ]
发布评论

评论列表(0)

  1. 暂无评论