javascript – 从2D数组生成3D数组

我正在尝试创建一个音乐游戏,我必须从基本的2D阵列生成3D数组.计划是在修改之前将2D阵列复制并粘贴到3D阵列中4次,如下所示:

var note3base = [
["C", "E", "G"],
["C#", "E#", "G#"],
["Db", "F", "Ab"],
["D", "F#", "A"],
["Eb", "G", "Bb"],
["E", "G#", "B"],
["F", "A", "C"],
["F#", "A#", "C#"],
["Gb", "Bb", "Db"],
["G", "B", "D"],
["Ab", "C", "Eb"],
["A", "C#", "E"],
["Bb", "D", "F"],
["B", "D#", "F#"],
["Cb", "Eb", "Gb"]
];

var note3 = new Array(4);

for (h=0;h<note3.length;h++){
note3[h] = note3base;
} //creates 4 copies of note3base in a 3d-array to be modified

for (i=0;i<note3[0].length;i++){
note3[1][i][1] = flat(note3[1][i][1]); //minor
note3[2][i][1] = flat(note3[2][i][1]);
note3[2][i][2] = flat(note3[2][i][2]); //dim
note3[3][i][2] = sharp(note3[3][i][2]); //aug
} //how did everything become the same?

现在问题似乎是for循环似乎将方法应用于每个单独的数组(0到3).

note3 [0] [1]的期望输出为CEG,note3 [1] [1]为C Eb G,注[2] [1]为C Eb Gb,注[3] [1]为CEG#.

任何帮助是极大的赞赏!

我已经在下面提供了(工作)尖锐和平坦的方法供参考:

function sharp(note){
  var newnote;
  if (note.charAt(1) == "#"){
    newnote = note.replace("#", "x");
  } else if (note.charAt(1) == "b"){
    newnote = note.replace("b", "");
  } else {
    newnote = note + "#";
  }
  return newnote;
 }

function flat(note){
   var newnote;
   if (note.charAt(1) == "#"){
     newnote = note.replace("#", "");
   } else {
     newnote = note + "b";
   }
   return newnote;
}
最佳答案
问题是当你为这样的数组分配一个等于这样的数组时:

someVar = someArray;

…它不会复制数组,它会创建对同一数组的第二个引用. (这适用于所有对象,而数组是一种对象.)所以在你的循环之后,你说过:

for (h=0;h<note3.length;h++){
  note3[h] = note3base;

… note3中的所有元素都指向相同的底层数组.

要制作实际副本,您可以使用循环手动复制所有元素,或者您可以使用.slice() method为您制作副本:

for (h=0;h<note3.length;h++){
  note3[h] = note3base.slice();
}

但这只会解决问题的一半,因为note3base本身包含对其他数组的引用,而.slice()只会复制这些引用.也就是说,虽然note3 [0]和note3 [1](和2和3)将引用不同的数组,note3 [0] [0]和note3 [1] [0]以及note3 [2] [0]和note3 [3] [0]将引用相同的[“C”,“E”,“G”]数组. (等等.)

你需要所谓的“深层复制”.您可以使用嵌套循环执行此操作:

for (h=0;h<note3.length;h++){
  // create this element as a new empty array:
  note3[h] = [];
  // for each 3-note array in note3base
  for (var k = 0; k < note3base.length; k++) {
    // make a copy with slice
    note3[h][k] = note3base[k].slice();
  }
}

说了这么多,我认为更简单的方法就是完成整个事情,而不是使用一个引用数组的note3base变量,使它成为一个返回一个新数组的函数:

function makeNote3Array() {
  return [
    ["C", "E", "G"],
    ["C#", "E#", "G#"],
    ["Db", "F", "Ab"],
    ["D", "F#", "A"],
    ["Eb", "G", "Bb"],
    ["E", "G#", "B"],
    ["F", "A", "C"],
    ["F#", "A#", "C#"],
    ["Gb", "Bb", "Db"],
    ["G", "B", "D"],
    ["Ab", "C", "Eb"],
    ["A", "C#", "E"],
    ["Bb", "D", "F"],
    ["B", "D#", "F#"],
    ["Cb", "Eb", "Gb"]
  ];
}

因为该函数使用数组文字,所以每次调用它时都会创建一个全新的数组数组.那么你可以执行以下操作,而不需要.slice()或嵌套循环:

var note3 = new Array(4);
for (h=0;h<note3.length;h++){
  note3[h] = makeNote3Array();
}

转载注明原文:javascript – 从2D数组生成3D数组 - 代码日志