JavaScript: проблемы передачи по ссылке при создании функции многомерного массива с неизвестным измерением - PullRequest
0 голосов
/ 25 июня 2018

Я публикую этот вопрос, потому что я пытаюсь создать функцию, которая позволяет кому-то создавать массив с множественным затемнением. Таким образом, пользователь вводит массив чисел, которые являются размерами массива (например, при вводе [2, 4, 3] будет получен многодатной массив 2x4x3) Я потратил пару часов, пытаясь представить алгоритм, который может сделать это в JS, и я придумал это:

Примечание: я использую Node.js v9.11.1

function generate(dimensions) {

  // SA = sub-array (I will use this several times here)

  // This array will store every SAs of the multi-dim array
  // E.g for a 2x4x3 array, it will store a 2-item array, a 4-item array and a 3-item array
  var arrays = []

  // This fills `arrays` with the SAs
  for (var i = 0; i < dimensions.length; i++) arrays.push(new Array(dimensions[i]).slice(0))

  // Here it gets a bit complex (at least for me!)
  // So what we do is that for each SA (except last), we fill it with copies of the current+1 SA
  // So the SA at index 1 will be filled with copies of the array at index 2
  // And the array at index 0 will be filled with arrays of index 1 (which was already filled because our for loop starts from the end)
  // The array at index 0 is our final multi-dim array

  // Goes from the before last SA to the first
  for (var current = dimensions.length-2; current !== -1; current--) {

    // Fills the current SA with index+1 SA
    for (var i = 0; i < arrays[current].length; i++) arrays[current][i] = arrays[current+1].slice(0)

  }

  // Returns first array, the complete one
  return arrays[0].slice(0)
}

Моя проблема в том, что даже если массив хорошо сгенерирован, некоторые SA передаются по ссылке, а не по значению, поэтому, когда я делаю

my_array = generate([2, 4, 3])
my_array[1][2][1] = "hi!" // Fill a random place with "hi!"

Затем, когда я делаю console.log(my_array), некоторые другие случаи многомерного массива заполняются тем же значением. Это означает, что где-то массив передается по ссылке, а не по значению, что странно потому что я проверил код несколько раз, и я не могу найти, откуда это может (я использую Array.slice() способ "скопировать" массив)

Я пропустил что-то огромное? Ваша помощь будет весьма признательна!

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

Я придумаю это:

function generate(dims) {
  if(dims.length > 0) {
    let array = new Array(dims[0]).fill(0);
    let childDims = dims.slice();
    childDims.shift();

    return array.map((el) => {
      return generate(childDims);
    });
  } else return 0;
}

let foo = generate([2, 3, 2]);
foo[0][0][1] = 'hmmmm';
console.log(foo);

Также используется рекурсия для создания многомерного массива. Но при создании массивов, как Вы видели, нужно быть осторожным, не передавая ссылки, а действительные копии массивов. Slice() даст Вам только мелкую копию.

0 голосов
/ 25 июня 2018

Если честно, не уверен, как вы пытаетесь создать массив с множественным затемнением, ..

Но первое, что приходит на ум, когда вы видите нечто подобное, это рекурсия.

например ..

function generate(dimensions) {
  if (!dimensions.length) throw new Error("no dims?");
  const dimsize = dimensions[0];
  if (dimensions.length === 1) {
    return new Array(dimsize).fill(null);
  }
  const ret = [];
  const subdims = dimensions.slice(1);
  for (let l = 0; l < dimsize; l+= 1) 
    ret.push(generate(subdims));
  return ret;
}

const my_array = generate([2, 4, 3])
my_array[1][2][1] = "hi!"

console.log(my_array);
...