Reputation: 93
I'm trying to create an object, at run time, to represent vertical axis ticks for a Google chart.
Given an array of MIDI (https://newt.phys.unsw.edu.au/jw/notes.html) note numbers nn, where the range is defined by the user, I need to transform this to an array of objects of the form {v: nn, f: notes[nn]}
(notes is an existing array of text names, such as "C4" for nn=60).
notes = ['A0', 'A#0', 'B0', 'C1', ... , 'C8']
and corresponding nn values would be:
nnArr = [21, 22, 23, 24, ... , 108]
The end results would be something like this:
vAxisTicks= [
{v: 56, f: notes[56-21]}, {v: 57, f: notes[57-21}, {v: 58, f: notes[58-21]}
]
etc
I think an approach is to use Array with .map but I can't see how to use that to get the keys in the objects, despite several forays into the literature!
Upvotes: 1
Views: 153
Reputation: 4241
If I understood correctly you want to generate like this?:
const notes = {};
const letters = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#'];
let num = 0;
for (let i = 21, y = 0; i <= 108; i++, y >= letters.length - 1 ? y = 0 : y++){
if (letters[y] == "C") num ++;
notes[i] = letters[y] + num;
}
//console.log(notes)
const output = Object.entries(notes).map(([key,val]) => {
return {v: key, f: val}
});
console.log(output)
//It could be generated in one loop with:
/*
const notesArr = [];
for (let i = 21, y = 0; i <= 108; i++, y >= letters.length - 1 ? y = 0 : y++){
if (letters[y] == "C") num ++;
notesArr.push({v: i, f: letters[y] + num});
}
console.log(notesArr)
*/
.as-console-wrapper { max-height: 100% !important; top: 0; }
Output is:
[
{
"v": "21",
"f": "A0"
},
{
"v": "22",
"f": "A#0"
},
{
"v": "23",
"f": "B0"
},
{
"v": "24",
"f": "C1"
},
...
]
Important are these lines:
for (let i = 21, y = 0; i <= 108; i++, y >= letters.length - 1 ? y = 0 : y++){
if (letters[y] == "C") num ++;
notes[i] = letters[y] + num;
}
that means loop from i = 21
to i = 108
- I got this from: https://newt.phys.unsw.edu.au/jw/notes.html.
Every iteration of the loop add on one to i
and add on one to y
unless y
is already equal to the last index of the letters array:
const letters = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#'];
if it is at the end (so y == 11
), then reset back to zero: y = 0
.
Then you have created a notes object like:
{21: 'A0', 22: 'A#0', 23: 'B0', 24: 'C1', ... , 108: 'C8'}
You can then loop over the entries with Object.entries(notes)
.
This gives you an array like this:
[[21, 'A0'], [22, 'A#0'], [23, 'B0'], [24, 'C1'], ... , [108, 'C8']]
Which you can loop over with .map()
to create your desired output.
NOTE: we could have just created this up-front in the for-loop but it seemed like you already had this notes object.
Alternatively:
If you want to take an array as input like [56, 57, 58]
Then you can do this:
const notes = {};
const letters = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#'];
let num = 0;
for (let i = 21, y = 0; i <= 108; i++, y >= letters.length - 1 ? y = 0 : y++){
if (letters[y] == "C") num++;
notes[i] = letters[y] + num;
}
//console.log(notes)
const inputNums = [56, 57, 58];
const output = inputNums.map(item => {
return {v: item, f: notes[item]}
});
console.log(output)
.as-console-wrapper { max-height: 100% !important; top: 0; }
output:
[
{
"v": 56,
"f": "G#3"
},
{
"v": 57,
"f": "A3"
},
{
"v": 58,
"f": "A#3"
}
]
Alternatively:
If I assume like I just edited your question, that you have an array for notes like:
notes = ['A0', 'A#0', 'B0', 'C1', ... , 'C8']
and corresponding nn values would be:
nnArr = [21, 22, 23, 24, ... , 108]
Then we can solve it very similarly:
const notes = [];
const letters = ['A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#'];
let num = 0;
for (let i = 21, y = 0; i <= 108; i++, y >= letters.length - 1 ? y = 0 : y++){
if (letters[y] == "C") num++;
notes.push(letters[y] + num);
}
//console.log(notes)
const input = [56, 57, 58]
const output = input.map(i => {
return {v: i, f: notes[i - 21]}
});
console.log(output)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1