0

i want to push items from one array to another but i'm getting only duplicates of last item. is there a way or better way of working this out? thanks

let nums = [{id:1, first_name: "sade", last_name: "Smith"}, {id:2, first_name: "Jon", last_name: "Doe"}];
let em = [];
let num2 = {id:null, name: ""}

nums.forEach(e => {
  num2.id = e.id;
  num2.name = `${e.first_name} ${e.last_name}`;
  em.push(num2)
});
console.log(em)  

1
  • This is because each time you're pushing num2, its the same object. Clone num2 then push Commented Jan 4, 2021 at 2:36

5 Answers 5

2

As mentioned in the other answers, the issue is that you're changing an existing object every iteration instead of adding a new one.

I'd like to add that that you can also use reduce instead (I personally prefer the syntax and it's a bit shorter):

let nums = [{id:1, first_name: "sade", last_name: "Smith"}, {id:2, first_name: "Jon", last_name: "Doe"}];
let em = [];
let num2 = {id:null, name: ""}

em = nums.reduce((accumulator, item) => {
 accumulator.push({
  id: item.id,
  name: `${item.first_name} ${item.last_name}`;
 })
}, [])

More info about the reduce function can be found in the MDN docs.


Why does it work like this?

If you want to know more about why your solution didn't work, it's important to understand that in JS there's a difference between primitive values and objects.

By assigning a variable that contains an object to another variable, you are not assigning a new object, but only pointing to an existing one instead. This causes coupling between your objects, they are pointing to the same object, as can be demonstrated here:

var obj1 = {name: 'Sherlock Holmes', country: 'England'}
var obj2 = obj1;

obj2.country = 'US';

console.log(obj1.country) // US
console.log(obj2.country) // US

Because of this, when you want to assign an object to another variable you need to clone its content, but create a new object, therefor the variable will point to a new object and not to the old one.

There are many ways to do it, but few simple ones are:

  1. Using the spread operator like this:

var obj1 = {name: 'Sherlock Holmes', country: 'England'}
var obj2 = { ...obj1 };

obj2.country = 'US';

console.log(obj1.country) // England
console.log(obj2.country) // US

  1. Stringifying then parsing using JSON.stringify and JSON.parse

var obj1 = {name: 'Sherlock Holmes', country: 'England'}
var obj2 = JSON.parse(JSON.stringify(obj1));

obj2.country = 'US';

console.log(obj1.country) // US
console.log(obj2.country) // US

There are more ways, and differences between those ways, if your object has nested objects as well, the replications might not occur correctly, at this point it's best to use a function that does the cloning for you, like lodash's deepClone function.

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

Comments

1

Just clone num2 and push the cloned object.

let nums = [{id:1, first_name: "sade", last_name: "Smith"}, {id:2, first_name: "Jon", last_name: "Doe"}];
let em = [];
let num2 = {id:null, name: ""}

nums.forEach(e => {
  const cloned = {...num2};
  cloned.id = e.id;
  cloned.name = `${e.first_name} ${e.last_name}`;
  em.push(cloned)
});
console.log(em)  

Comments

1

Your issue is that each time, you're adding the same object to the list, num2. num2 itself is not changing through each iteration of the loop.

This is an effect of you never reassigning num2 to anything new, and the fact that the list nums is keeping track of a list of pointers to objects, which means it doesn't actually copy num2 into itself each time, it just puts num2's pointer in.

You should either 1) clone it or just 2) make a new object then push it to the list.

let nums = [{id:1, first_name: "sade", last_name: "Smith"}, {id:2, first_name: "Jon", last_name: "Doe"}];
let em = [];
let num2 = {id:null, name: ""}

nums.forEach(e => {
  let temp_num = {...num2};
  temp_num.id = e.id;
  temp_num.name = `${e.first_name} ${e.last_name}`;
  em.push(temp_num)
});
console.log(em)  

Comments

1

It is a fairly simple map() operation to create the new array from the original

let nums = [{id:1, first_name: "sade", last_name: "Smith"}, {id:2, first_name: "Jon", last_name: "Doe"}];

let res = nums.map(({id, first_name:fn, last_name:ln}) => ({id, name: `${fn} ${ln}`}));

console.log(res)

Comments

0

That's because you keep pushing the same object to the em array in each iteration in the forEach loop.

A simple approach would be to do this:

const nums = [{id:1, first_name: "sade", last_name: "Smith"}, {id:2, first_name: "Jon", last_name: "Doe"}];
const em = [];

nums.forEach(e => {
  em.push({id: e.id, name: `${e.first_name} ${e.last_name}`});
});

console.log(em);

You could also use the map functionality on arrays:

const nums = [{id:1, first_name: "sade", last_name: "Smith"}, {id:2, first_name: "Jon", last_name: "Doe"}];
const em = nums.map((item) => ({id: item.id, name: `${item.first_name} ${item.last_name}`}));
console.log(em);

Essentially, we are creating a new object and pushing it into the em array in every iteration in the loop and in the process, removing the need for the num2 object that you've declared.

In addition, the em variable can be made const since using a const variable does not mean that the value it holds is immutable; we're simply pushing new elements into the array which is perfectly possible.

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.