1

I have a data set like following table.

+------+---------+----+----+----+----+-------+----------+
| Year | Subject | A  | B  | C  | F  | Total | PassRate |
+------+---------+----+----+----+----+-------+----------+
| 2015 | Maths   | 12 | 20 | 10 |  5 |    47 |       80 |
| 2015 | Sinhala | 18 | 14 |  5 | 10 |    47 |       75 |
| 2016 | Maths   | 25 | 15 |  4 |  8 |    52 |       25 |
| 2016 | Sinhala | 20 | 12 |  2 | 18 |    52 |       60 |
+------+---------+----+----+----+----+-------+----------+

I want to store those data in JavaScript array. So I have following code.

var firstArray = [];
firstArray.push(['Year', 'Subject', 'A', 'B', 'C', 'F', 'Total', 'PassRate']); // headers
firstArray.push([2015, 'Maths', 12, 20, 10, 5, 47, 80]); // 1st row
firstArray.push([2015, 'Sinhala', 18, 14, 5, 10, 47, 75]) // 2nd row
console.log(firstArray);

If I need to read how many "B",s in Maths for 2015, I need to run firstArray[1][3].

That is not readable. I mean it is hard to find what it means firstArray[1][3].

So is there way to build my array more readable way like firstArray[2015]['maths'] if I want to read how many "B",s in Maths for 2015

1
  • 1
    You need an array of objects. Commented Aug 8, 2018 at 6:51

3 Answers 3

8

Sounds like you want an object indexed by year, containing objects indexed by subject:

const years = {
  '2015': {
    Maths: {
      A: 12, B: 20, C: 10, F: 5, Total: 47, PassRate: 80
    },
    Sinhala: {
      A: 18, B: 14, C: 5, F: 10, Total: 47, PassRate: 75
    },
  },
  '2016': {
    // ...
  }
}
console.log(years['2015'].Maths);

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

Comments

1

Your purpose is correct, readability of code is very important.

It's not easy and there is no right path to follow, but I try to give you some hints on how to change your code.

First point: naming.

This is very hard, and often even experienced developer need to rename variables as they can't get the proper name at the first time.

Your variable is firstArray and this of course have low meaning and you can just say it is an array and it is the first...

Nothing about what the array is containing.

A better name could be studentsScoreByYear.

The improvement of this name is that it try to address the meaning of the content.

Then the index ad magic numbers.

Of course you need numbers to get a field from an array, and if you just use the proper integer in the code is very complicated to remember what this field is.

A way is to avoid array and use hash map, in javascript plain objects. So you can give to each field a name.

If you can't abbandon the array for whatever reason, you can improve here too, just use constants to save the proper indexes:

 var MATHS = 1;
 var SCORE_OF_B = 3;

 var studentsScoreByYear= [
    ['Year', 'Subject', 'A', 'B', 'C', 'F', 'Total', 'PassRate'],
    [2015, 'Maths', 12, 20, 10, 5, 47, 80],
    [2015, 'Sinhala', 18, 14, 5, 10, 47, 75]
];

console.log(studentsScoreByYear[MATHS][SCORE_OF_B]);

There are other ways of course, this is just a possibility.

Comments

0

A list of objects is what you want to represent your data in a readable format.

As for selecting data:

  • You can filter an array by using the filter method on the array.
  • You can change the contents or isolate a parameter with the map method on the array.
  • You can perform arithmetic operations with the reduce method on the array.

var data = [
    { year: 2015, subject: 'Maths', a: 12, b: 20, c: 10, f: 5, total: 47, passrate: 80 },
    { year: 2015, subject: 'Sinhala', a: 18, b: 14, c: 5, f: 10, total: 47, passrate: 75 },
    { year: 2016, subject: 'Maths', a: 25, b: 15, c: 4, f: 8, total: 52, passrate: 25 },
    { year: 2016, subject: 'Sinhala', a: 20, b: 12, c: 2, f: 18, total: 52, passrate: 60 },
];
console.log("Present All:");
console.log(data
    .map(function (row) {
    return [row.year, row.subject, row.a, row.b, row.c, row.f, row.total, row.passrate].join(", ");
})
    .join("\n"));
console.log("Count `B` in `Maths` in 2015");
console.log(data
    .filter(function (row) { return row.year === 2015 && row.subject === "Maths"; })
    .map(function (row) { return row.b; })
    .reduce(function (accumulator, currentValue) { return accumulator + currentValue; }, 0));

Sidenote

The eagle-eyed out there has probably already spotted that the map and filter calls are redundant in the "Present All" example as i could simply have put:

data.reduce(function (accumulator, row) { return accumulator + (row.year === 2015 && row.subject === "Maths" ? row.b : 0); }, 0);

While the above code is "smarter", i think the more verbose answer using map and filter will be of more use to anyone trying to learn JavaScript array handling and JavaScript objects.

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.