1

I am trying to transform the objects in an array adding a new property number. The value of this property must be obtained from the array set using sequential values, so that the first object should have the value 1 the second the value 3 and the third the value 6 the fourth the value 1 again and so on ...

This is what I've been trying

const set = [1, 3, 6];
const data = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }];
let position = 0;

const getItem = () => {
  if (position === 0) {
    position += 1;

    return set[0];
  }

  if (position <= set.length - 1) {
    return set[position];
  }

  return set[0];
};

const output = data.map((entry, index) => ({ ...entry, number: getItem() }));

console.log(output);

And this is the expected output

[
  { id: 1, number: 1 },
  { id: 2, number: 3 },
  { id: 3, number: 6 },
  { id: 4, number: 1 },
  { id: 5, number: 3 },
  { id: 6, number: 6 },
];

2 Answers 2

2

getItem needs to wrap position back to the beginning. The easy way to do that is to use position = (position + 1) % set.length, like this:

let position = -1;
const getItem = () => {
  position = (position + 1) % set.length;
  return set[position];
};

Live copy:

const set = [1, 3, 6];
const data = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }];
let position = -1;

const getItem = () => {
  position = (position + 1) % set.length;
  return set[position];
};

const output = data.map((entry, index) => ({ ...entry, number: getItem() }));

console.log(output);

...although thinking about it, there's no particular reason position itself has to wrap, so long as you use % set.length when retrieving from set:

let position = 0;
const getItem = () => {
  return set[position++ % set.length];
};

I generally wrap it (the first version) if the index is going to survive like that.


Or if you only need to do this within map, you don't need position or getItem at all, just use index % set.length in map:

const output = data.map((entry, index) => ({ ...entry, number: set[index % set.length] }));

Live copy:

const set = [1, 3, 6];
const data = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }];
let position = -1;

const output = data.map((entry, index) => ({ ...entry, number: set[index % set.length] }));

console.log(output);


The % length thing works because it's a remainder operation: x % y is the remainder of integer division of x by y. 0 % 3 is 0, 1 % 3 is 1, 2 % 3 is 2, and then 3 % 3 is 0 again and the cycle repeats.

Sign up to request clarification or add additional context in comments.

Comments

2

You could take a closure over the index (adjusted by the remainder with length of the array) and return new objects.

const
    numbers = [1, 3, 6],
    data = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }],
    result = data.map((i => o => ({ ...o, number: numbers[i++ % numbers.length] }))(0));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.