7

I have been trying to push an array of 3 values to an array to create an AOA. However my expected output is not coming out correct.

Input data looks something like the following

[
{id:xxxxx,
date:VALUE,
date:VALUE,
..months worth
},
{id:xxxx2,
date:VALUE,
date:VALUE,
..months worth
},
..loads of entries
]

please see the snip of code below.

arrayOfObjects.forEach(e =>{            
            let entry = [];
            entry[0] = e.id;            
            let PC = Object.values(e)        
            let Dates = Object.keys(e)
            PC.shift();
            Dates.shift();
            for(let i = 0; i <PC.length; i++){
                if(PC[i] === 'No Data'){
                    entry[2] = 0;
                    entry[1] = Dates[i];                   
                } else {
                    entry[2] = PC[i];
                    entry[1] = Dates[i];
                }
                finalArray.push(entry);
            }

        })

I am getting an array of outputs that contain the a static date

[
  ...
  [ 'NAAAAD', '10/31/19', 0 ],
  [ 'NAAAAD', '10/31/19', 0 ],
  [ 'NAAAAD', '10/31/19', 0 ],
  [ 'NAAAAD', '10/31/19', 0 ],
  [ 'NAAAAD', '10/31/19', 0 ],
  [ 'NAAAAD', '10/31/19', 0 ],
  [ 'NAAAAD', '10/31/19', 0 ],
  ...
]

When i want to see the date increment.

[
  ...
  [ 'NAAAAD', '10/25/19', 0 ],
  [ 'NAAAAD', '10/26/19', 0 ],
  [ 'NAAAAD', '10/27/19', 0 ],
  [ 'NAAAAD', '10/28/19', 0 ],
  [ 'NAAAAD', '10/29/19', 0 ],
  [ 'NAAAAD', '10/30/19', 0 ],
  [ 'NAAAAD', '10/31/19', 0 ],
  ...
]

I have console.log(entry) just before it gets pushed into the array and i contains the correct information at that point? I have moved the finalArray.push(entry) to be within the if statements directly under the line where entry is correct.

What is going on here? I am unable to find anything like this, I've considered the scope of variables, but they all seems correct.

Thanks

Ryan

Peachman1997
  • 183
  • 1
  • 12
  • 4
    You are pushing the reference to the same `entry` object into your array all the time. You need to create a _new_ object each time. – 04FS Jan 17 '20 at 12:52
  • @04FS Hi, i have resigned the value of `entry` before i push it into the array? so should contain the new data? – Peachman1997 Jan 17 '20 at 12:53
  • @Peachman1997 No you have not, it's still the same Object. You have assigned new values to the properties of that object, but the object you push is still the same; all entries you push point to the same object, and its latest properties. – Thomas Jan 17 '20 at 12:55
  • @Thomas This isn't making sense to me... I change the properties of the array and push that array with new entries into the finalArray. it the same named Object, but the updated values do not update? – Peachman1997 Jan 17 '20 at 12:58
  • @Peachman1997 changing the properties of an object doesn't change the identity of the object. If you change your clothes, does this make you a different person? – Thomas Jan 17 '20 at 13:01
  • @Thomas You would expect to see the change in properties though? if i was to push myself into an array with clothes A on. Then change clothes and push myself into the array, you would see me twice with different clothes on? – Peachman1997 Jan 17 '20 at 13:04
  • 1
    @Peachman1997 no, I would expect to see let's say your name (or something else to identify you as a person) twice in the list, and as soon as I "resolve" who's behind that name, I would see YOU. However you may look NOW. Not you in version 1 vs you in version 2, ... You, the way you look at the moment I look at you; no matter how many times you may change before or after that. – Thomas Jan 17 '20 at 13:08
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/206148/discussion-between-peachman1997-and-thomas). – Peachman1997 Jan 17 '20 at 13:12
  • You are not pushing the object into your array, only the _reference_ to your object. All your array entries refer to the same, _single_ object. The changes you make to this object’s properties are reflected in all your array entries, _because_ they all point to the exact same object. – 04FS Jan 17 '20 at 13:14
  • Mind Blown, this has never happened before? I think i sort of understand why. thanks everyone! – Peachman1997 Jan 17 '20 at 13:18
  • Does this answer your question? [How to push object to array from for loop properly in JavaScript?](https://stackoverflow.com/questions/36602160/how-to-push-object-to-array-from-for-loop-properly-in-javascript) – ggorlen Jun 15 '21 at 15:04

2 Answers2

6

I think you might need to clone the object every time before pushing it:

arrayOfObjects.forEach(e =>{            
        let entry = [];
        entry[0] = e.id;            
        let PC = Object.values(e)        
        let Dates = Object.keys(e)
        PC.shift();
        Dates.shift();
        for(let i = 0; i <PC.length; i++){
            let newEntry = Object.assign([], entry);
            if(PC[i] === 'No Data'){
                newEntry[2] = 0;
                newEntry[1] = Dates[i];                   
            } else {
                newEntry[2] = PC[i];
                newEntry[1] = Dates[i];
            }
            finalArray.push(newEntry);
        }

    })
TKoL
  • 13,158
  • 3
  • 39
  • 73
  • 1
    It works because every time you pushed `entry` onto the array, you were pushing the same array on, and every time you did `entry[2] = 0; entry[1] = Dates[i]`, you were just changing the values of the same array. `let newEntry = Object.assign([], entry);`, on the other hand, makes a copy of the entry and pushes that one on instead. – TKoL Jan 17 '20 at 13:20
1

instead of this complicated approach why don't you just create a new, distinct entry for every new distinct row you want to add to the list.

arrayOfObjects.forEach(e => {
  for (let [key, value] of Object.entries(e)) {
    if (value === 'No Data') {
      value = 0; // change the variable `value`
    }
    // push a new row
    finalArray.push([ e.id, key, value ]);
  }
})

or

arrayOfObjects.forEach(e => {
  for (let [key, value] of Object.entries(e)) {
    finalArray.push([ e.id, key, value === 'No Data' ? 0 : value ]);
  }
})
Thomas
  • 11,958
  • 1
  • 14
  • 23
  • Yeah, i ended up trying this approach to confirm my understanding, loving that second code snip, very clean and tidy. – Peachman1997 Jan 17 '20 at 14:09