Thursday 23 March 2017

Spot The Bug: Nested JSON Array Trap

Spot The Bug is back, and bigger and meaner than ever! Huzzah!

Woohoo!

Sorry, couldn't resist a bit of melodrama.

Some time ago, I was writing a little mobile application to track my smoking habits (it's a nasty habit, kids - don't start!) and decided to create a little bar graph to tabulate the data. No errors were reported, but somehow the data wouldn't display right.

Here's the data, in JavaScript array format. It's basically an array of 5 days' worth of data. Each day is an array element. This array element, in turn, comprises of a number of objects, each representing the hour (h) and the minute (m) that I smoked that cigarette.
            [
                [
                    {h:6,m:43},
                    {h:7,m:08},
                    {h:7,m:45},
                    {h:9,m:09},
                    {h:10,m:13},
                    {h:13,m:11},
                    {h:14,m:24},
                    {h:16,m:25},
                    {h:17,m:15},
                    {h:21,m:53},
                    {h:23,m:19},
                ],
                [
                    {h:7,m:02},
                    {h:7,m:18},
                    {h:8,m:55},
                    {h:9,m:02},
                    {h:9,m:55},
                    {h:10,m:12},
                    {h:10,m:23},
                    {h:12,m:43},
                    {h:13,m:20},
                    {h:14,m:55},
                    {h:15,m:25},
                    {h:17,m:10},
                    {h:20,m:52},
                    {h:23,m:09},
                ],
                [
                    {h:6,m:57},
                    {h:7,m:38},
                    {h:7,m:43},
                    {h:8,m:08},
                    {h:8,m:45},
                    {h:9,m:09},
                    {h:9,m:13},
                    {h:10,m:43},
                    {h:12,m:11},
                    {h:14,m:24},
                    {h:16,m:25},
                    {h:18,m:15},
                    {h:19,m:53},
                    {h:23,m:19},
                    {h:23,m:19},
                ],
                [
                    {h:6,m:36},
                    {h:6,m:44},
                    {h:7,m:04},
                    {h:7,m:15},
                    {h:7,m:48},
                    {h:9,m:03},
                    {h:10,m:11},
                    {h:12,m:23},
                    {h:13,m:40},
                    {h:14,m:58},
                    {h:16,m:09},
                    {h:17,m:11},
                    {h:21,m:11},
                    {h:23,m:04},
                    {h:23,m:55},
                ],
                [
                    {h:0,m:31},
                    {h:6,m:22},
                    {h:6,m:59},
                    {h:7,m:09},
                    {h:8,m:15},
                    {h:9,m:21},
                    {h:10,m:22},
                    {h:12,m:53},
                    {h:13,m:20},
                    {h:14,m:25},
                    {h:15,m:31},
                    {h:17,m:28},
                    {h:21,m:07},
                    {h:22,m:29},
                    {h:22,m:50},
                    {h:22,m:55},
                    {h:23,m:19},
                ],
            ]


I would stringify the data and store it in localStorage, and then when I needed the data, I retrieved it from localStorage and tabulated it with this code.
            var smoke_record=JSON.parse(json_str);
            var tr;
            var td;
            var table=document.getElementById("smoke_graph");

            for (var i=0;i<smoke_record.length;i++)
            {
                tr=document.createElement("tr");
                td=document.createElement("td");
                td.innerHTML=i+1;
                tr.appendChild(td);

                td=document.createElement("td");

                for (var j=0;j<smoke_record.length;j++)
                {
                    td.innerHTML=td.innerHTML+"|";
                }

                tr.appendChild(td);
                table.appendChild(tr);
            }



What went wrong

This, for starters. Every day reported that I had smoked exactly five cigarettes.


The pipe symbol was supposed to represent each stick. I'm pretty sure I didn't smoke exactly five cigarettes a day. No errors were reported in console.

Why it went wrong

Well, the number 5 gave me a clue. What else had five elements? The parent array, of course! I was iterating through the parent array, smoke_record, instead of the children!
                for (var j=0;j<smoke_record.length;j++)
                {
                    td.innerHTML=td.innerHTML+"|";
                }


How I fixed it

Here's the fix. I'm ashamed to report that it was a very easy fix, because this mistake was so amateurish it shouldn't have been made at all.
                for (var j=0;j<smoke_record[i].length;j++)
                {
                    td.innerHTML=td.innerHTML+"|";
                }



This is the correct (and very unhealthy) graphical representation.


Moral of the story

A lot of misery can be found in nested arrays and nested For loops. They're not insurmountable, by any means, but they sure are annoying and treacherous.

Now that's what I call a smokin' hot fix.
T___T

No comments:

Post a Comment