1

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!

1 Answer 1

1

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; }

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

3 Comments

Brilliant - many thanks. I tested it and I can certainly use it. Now I will try to understand it a bit more!
You're welcome - I added new comments in the answer to hopefully make it clearer what I am doing.
I also tried to edit your question (it's now in edit review) - in general, try to give all input and output data in the question so that people don't have to guess - stackoverflow.com/help/minimal-reproducible-example

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.