在Javascript中基于其他信息填充数组的最有效方法是什么?

What is the most efficient way to populate an array based on other information in Javascript?

本文关键字:数组 填充 有效 是什么 方法 信息 Javascript 于其他 其他      更新时间:2023-09-26

我有一个名为NoteArray的数组,在Javascript中大小为16。我还有一个名为NoteToNumberMapping的静态2D数组,大小为11x12,如下所示。现在,作为输入,我让用户选择12个标准音符的任意组合(c - c# - d - d# -E-F-F#-G-G#-A-A#-B),或者什么都不选择。如。"C G G#",或"D D# G A B",或blank等。注:如有必要,笔记可能会"乱了次序"(例如:"D A C c# ")

对于"C G g#"的例子,我想参考二维数组,看到在八度程0中,C、G和g#对应的数字是0,7和8。同样,对于八度1,数字是12、19和20。按照这种方式继续,前16个数字是:0、7、8、12、19、20、24、31、32、36、43、44、48、55、56、60。

我想把这16个数字分配给我的初始NoteArray。

我的方法

我将2D数组实现为包含128个元素的1D数组,其中包含字母。所以第0项是C0,第1项是c# 0,直到第127项(G10)。我想利用2D表中的值是1-127的线性级数这一事实。但我最终用了3个嵌套的for循环,仍然无法让它工作。在Javascript中实现这一点的有效方法是什么?

您可以首先创建一个从音符名称到相对音符编号的查找表:

var relativeNoteNumberTable = {
    'C': 0, 'C#': 1, 'D': 2, 'D#':  3, 'E':  4, 'F': 5, 'F#': 6,
    'G': 7, 'G#': 8, 'A': 9, 'A#': 10, 'B': 11
};

则可以相对容易地得到所选音符的相对音符号:

var selectedNotes = 'C G G#';
var relativeNoteNumbers = selectedNotes.split(' ')
    .filter(function(note) { return note })  // remove blanks
    .map(function(note) { return relativeNoteNumberTable[note] });
console.log(relativeNoteNumbers);  // [0, 7, 8]

然后观察每一个八度,MIDI音符数增加12。如果你想要每个八度都有这些音符,直到你有16个音符,你可以这样做:

var notes = [];
while(notes.length < 16) {
    notes.push(Math.floor(notes.length / relativeNoteNumbers.length) * 12 +
               relativeNoteNumbers[notes.length % relativeNoteNumbers.length]);
}

您应该能够在线性时间复杂度下做到这一点。你应该使用一个对象来存储你的2D数组,像这样:

my2dArray = {
  "0C": 0,
  "0C#": 1,
  "0D": 2,
  ...
}

然后,您将不必遍历2D数组来获得您想要的映射值。您只需执行my2array [myKey],它具有恒定的查找时间。