0

I want to improve my ugly code to something more clean and simple. How can I shorten this code?

if (this.foo < 2) {
  return (this.result = [ { year: 1 } ]);
}
if (this.foo < 3) {
  return (this.result = [ { year: 1 }, { year: 2 } ]);
}
if (this.foo < 4) {
  return (this.result = [ { year: 1 }, { year: 2 }, { year: 3 } ]);
}
if (this.foo < 5) {
  return (this.result = [ { year: 1 }, { year: 2 }, { year: 3 }, { year: 4 } ]);
}
if (this.foo < 6) {
  return (this.result = [ { year: 1 }, { year: 2 }, { year: 3 }, { year: 4 }, { year: 5 } ]);
}
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
  • The task can be done by a for-loop, – The KNVB May 31 '21 at 06:19
  • 4
    `return this.result = Array.from({ length: Math.floor(this.foo) }, (_, index) => ({ year: index + 1 }));`? Familiarize yourself with [how to access and process objects and arrays](/q/11922383/4642212) and how to [create objects](//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer) and use the available [`Object`](//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#Static_methods) and [`Array`](//developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#Static_methods) methods (both static and on prototype). – Sebastian Simon May 31 '21 at 06:19
  • 1
    It would be better if you described your question. For example _"I want to produce an array of length `this.foo - 1` filled with objects of `{year: n}` where `n` is the 1-based index of the object in the array"_. Sound about right? – Phil May 31 '21 at 06:20
  • @Phil thank you for your specific comments!! My English is not good so it is little difficult to specify what I want TT – Ellen Mina Kim May 31 '21 at 06:23
  • @SebastianSimon 5 star for using `Array.form` – Vivek Bani May 31 '21 at 06:23
  • 1
    [Related](//google.com/search?q=site%3Astackoverflow.com+js+create+array+with+n+objects+with+index+as+value): [How to create an array containing 1…N](/q/3746725/4642212). – Sebastian Simon May 31 '21 at 06:24
  • @EllenMinaKim all good, a description of a problem usually makes it easier to solve and sometimes you even solve it yourself while trying to explain it (see [rubber duck debugging](https://en.wikipedia.org/wiki/Rubber_duck_debugging)). Looks like you got some good answers already. – Phil May 31 '21 at 06:33

4 Answers4

7

Create an array with Array, and use Array.prototype.map.

function func(foo) {
  return Array(foo).fill().map((f, i) => ({ year: i + 1 }));
}

console.log(func(1));
console.log(func(3));
zmag
  • 7,825
  • 12
  • 32
  • 42
4

What you’ve shown is equivalent to this (except this goes beyond five elements, but also beyond one in the other direction):

return this.result = Array.from({
  length: Math.floor(this.foo)
}, (_value, index) => ({
  year: index + 1
}));

This assumes that this statement is inside a function (otherwise, return wouldn’t work).

A more reasonable length may be Math.max(0, Math.min(2 ** 32 - 1, Math.floor(this.foo))) which clamps1 the length to at least 0 and at most 232 − 1, the maximum Array length.

If you want to always have at least one element in your array, then use Math.max(1,) instead.

Returning an assignment (i.e. return this.result =;) is frowned upon. The best practice is to separate these statements2:

this.result = Array.from({
  length: Math.max(0, Math.min(2 ** 32 - 1, Math.floor(this.foo)))
}, (_value, index) => ({
  year: index + 1
}));

return this.result;

Array.from is used with both arguments: the first one is the “array-like” object { length: Math.max(0, Math.min(2 ** 32 - 1, Math.floor(this.foo))) } which gets converted to a proper Array object. In this case, an array with a length of Math.floor(this.foo) is initialized (clamped to the range of possible Array lengths). The second argument maps each value at a certain index to an object with the year property with the value index + 1. _value isn’t used (it’s undefined anyway).

The advantage to use Array.from(array-like,mapping-function) over e.g. .fill().map() is that only a single array is created in memory. Array().fill().map() creates two new arrays: the first one at Array().fill(), the second one at .map(). Therefore, the Array.from approach is more memory-efficient.


1: Maybe soon we’ll finally get a Math.clamp method…

2: Technically, this would be equivalent. If this.result is a getter / setter, there may be an observable difference.

const result = Array.from({
    length: Math.max(0, Math.min(2 ** 32 - 1, Math.floor(this.foo)))
  }, (_value, index) => ({
    year: index + 1
  }));

this.result = result;

return result;
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
2

try this oneliner

let x=3;
let result = [ ...Array(x).keys() ].map(item=> {return{"year":item}});
console.log(result);
Aditya Joshi
  • 1,033
  • 7
  • 20
1
let arr = [];

for(let i = 1; i<this.foo;i++){ 
    arr.push({ 'year':i}) 
};

console.log(arr);

Vivek Bani
  • 3,703
  • 1
  • 9
  • 18