简体   繁体   中英

adding data to an array inside an object adds to all arrays

I have an array of objects with upload-data from users. Now I tried to change this array so I get datasets for a chart.js upload graph.

The Idea was to take all the days (I never know how many there are), the number of uploads per hour on that day, and put it in an array of objects for my graph. Everything works quite fine, except that I do not get an hourly upload per day but one upload-array that looks the same for all days.

According to my sample variable Uploads I should get two Objects with different data-arrays but they are the same.

can anyone tell me where I made my mistake?

 //my sample Data let Uploads = [{ user: 'user1', files: [{ uploadToServerTime: '21:12:2018 09:15:00' }] }, { user: 'user2', files: [{ uploadToServerTime: '22:12:2018 10:17:00' }] }, { user: 'user3', files: [{ uploadToServerTime: '22:12:2018 09:14:00' }] }] //the hourlyUpload Array has a length of 24 for each hour of the day let hourlyUpload = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let dailyUploadtemp = []; let dailyUpload = []; let hour; let day; let uploadMoment; for (let x of Uploads) { if (x.hasOwnProperty('files')) { for (let y of x.files) { if (y.hasOwnProperty('uploadToServerTime')) { uploadMoment = moment(y.uploadToServerTime, ['DD.MM.YYYY HH:mm:ss']); day = uploadMoment.format('DD.MM.YYYY'); dailyUploadtemp.push({ label: day, data: hourlyUpload }) } } } } dailyUpload = _.uniqBy(dailyUploadtemp, 'label'); //now I have an array of Objects with a set of empty hours for each day an upload has taken place for (let x of Uploads) { if (x.hasOwnProperty('files')) { for (let y of x.files) { if (y.hasOwnProperty('uploadToServerTime')) { uploadMoment = moment(y.uploadToServerTime, ['DD.MM.YYYY HH:mm:ss']); hour = uploadMoment.format('H'); day = uploadMoment.format('DD.MM.YYYY'); for (let z of dailyUpload) { if (z.label === day) { //here is something wrong. The Amount is added to every data, not only to z.data z.data[hour] = (z.data[hour] + 1); } } } } } } let ctx = document.getElementById("myChart").getContext("2d"); let myChart = new Chart(ctx, { type: 'line', data: { labels: ['00:00','01:00','02:00','03:00','04:00','05:00','06:00','07:00','08:00','09:00','10:00','11:00','12:00','13:00','14:00','15:00','16:00','17:00','18:00','19:00', '20:00','21:00','22:00','23:00'], datasets: dailyUpload }, options: { //responsive: false, animation: { duration: 1000, easing: 'easeOutQuad' }, scales: { xAxes: [{ type: 'time', time: { parser: "HH:mm", unit: 'hour', unitStepSize: 1, displayFormats: { 'minute': 'HH:mm', 'hour': 'HH:mm', min: '00:00', max: '23:59' } } }] } } }); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script> <p>There should be two different lines, but I only get two lines with the same datapoints</p> <canvas id="myChart" width="800" height="400"></canvas> 

PS: I'm well aware that those loops could be solved more elegant or faster, but it works this way, and if I do it step by step it's easier for me to understand what i am doing.

Your issue is here :

dailyUploadtemp.push({
   label: day,
   data: hourlyUpload
})

dailyUploadtemp is an object and its data property is a reference to the hourlyUpload array.

Every one of your object has a reference to the same array. So, if you're updating this array, the modification is reflected in all of your dailyUpload objects.

You can solve this by cloning your array when creating the data property in your dailyUploadTemp object . One way to do so is to use Array.prototype.slice :

dailyUploadtemp.push({
    label: day,
    data: hourlyUpload.slice()
})

 //my sample Data let Uploads = [{ user: 'user1', files: [{ uploadToServerTime: '21:12:2018 09:15:00' }] }, { user: 'user2', files: [{ uploadToServerTime: '22:12:2018 10:17:00' }] }, { user: 'user3', files: [{ uploadToServerTime: '22:12:2018 09:14:00' }] }] //the hourlyUpload Array has a length of 24 for each hour of the day let hourlyUpload = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let dailyUploadtemp = []; let dailyUpload = []; let hour; let day; let uploadMoment; for (let x of Uploads) { if (x.hasOwnProperty('files')) { for (let y of x.files) { if (y.hasOwnProperty('uploadToServerTime')) { uploadMoment = moment(y.uploadToServerTime, ['DD.MM.YYYY HH:mm:ss']); day = uploadMoment.format('DD.MM.YYYY'); dailyUploadtemp.push({ label: day, data: hourlyUpload.slice() }) } } } } dailyUpload = _.uniqBy(dailyUploadtemp, 'label'); //now I have an array of Objects with a set of empty hours for each day an upload has taken place for (let x of Uploads) { if (x.hasOwnProperty('files')) { for (let y of x.files) { if (y.hasOwnProperty('uploadToServerTime')) { uploadMoment = moment(y.uploadToServerTime, ['DD.MM.YYYY HH:mm:ss']); hour = uploadMoment.format('H'); day = uploadMoment.format('DD.MM.YYYY'); for (let z of dailyUpload) { if (z.label === day) { //here is something wrong. The Amount is added to every data, not only to z.data z.data[hour] = (z.data[hour] + 1); } } } } } } let ctx = document.getElementById("myChart").getContext("2d"); let myChart = new Chart(ctx, { type: 'line', data: { labels: ['00:00','01:00','02:00','03:00','04:00','05:00','06:00','07:00','08:00','09:00','10:00','11:00','12:00','13:00','14:00','15:00','16:00','17:00','18:00','19:00', '20:00','21:00','22:00','23:00'], datasets: dailyUpload }, options: { //responsive: false, animation: { duration: 1000, easing: 'easeOutQuad' }, scales: { xAxes: [{ type: 'time', time: { parser: "HH:mm", unit: 'hour', unitStepSize: 1, displayFormats: { 'minute': 'HH:mm', 'hour': 'HH:mm', min: '00:00', max: '23:59' } } }] } } }); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script> <p>There should be two different lines, but I only get two lines with the same datapoints</p> <canvas id="myChart" width="800" height="400"></canvas> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM