Почему изменения, внесенные в ячейку, распространяются на другие ячейки в этом двумерном массиве, создаваемом с помощью fill?
У меня проблема с этим двумерным массивом в JS. Когда я меняю a[1][0]
, с ним меняется a[0][0]
. Что-то не так в том, как я его инициализирую? Если да, как я могу его инициализировать правильно?
>var a = Array(100).fill(Array(100).fill(false));
>a[0][0]
>false
>a[1][0]
>false
>a[1][0] = true
>true
>a[1][0]
>true
>a[0][0]
>true
Ответы
Ответ 1
var a = Array(100).fill(Array(100).fill(false));
a
содержит массив, каждый элемент которого ссылается на массив. вы заполняете внешний массив массивом, который содержит все ложные значения. Внутренний массив создается только один раз, и ссылка на один и тот же массив передается каждому элементу внешнего массива, поэтому, если вы выполняете операцию над одним элементом, она также отражается и на других элементах.
Это фактически эквивалентно
var a1 = Array(100).fill(false);
var a = Array(100).fill(a1);
здесь a
получает 100 элементов, имеющих ссылку на тот же массив a1
. Поэтому, если вы меняете один элемент a
, все элементы меняются, так как они являются ссылками на один и тот же массив.
вам нужно будет заполнить каждый элемент внешнего массива новым массивом. вы можете сделать что-то вроде этого:
var a = [];
for(var i=0; i<100; i++)
a.push(Array(100).fill(false));
Ответ 2
Весь массив будет заполнен ссылками на тот же объект (второй размер) массива.
Чтобы заполнить его отдельными объектами, вам нужно сделать что-то вроде этого:
const a = Array(100).fill(false).map(x => Array(100).fill(false));
a[0][0] = true;
console.log(a[0][0]);
console.log(a[0][1]);
console.log(a[1][1]);
Ответ 3
Ваша проблема в том, что вы используете второй Array(100).fill(false)
в каждой позиции первого массива. Поэтому, когда вы меняете одно значение во втором измерении, оно изменяется в каждой отдельной позиции массива. Если вы хотите этого избежать, вам нужно создать новый массив для каждой позиции исходного.
var x = Array(100).fill().map(x => Array(100).fill(false));
Ответ 4
то, что вы здесь делаете, добавляет один и тот же объект массива в каждый индекс большего массива.
Итак, когда вы делаете
Array(x).fill(Array(y).fill(false));
В действительности вы делаете следующее:
Array(x).fill(Y); // i.e. X.fill(Y)
Теперь, когда вы меняете Y, вы получите одинаковое значение при каждом индексе X.
Вы должны использовать цикл для заполнения данных, когда сами данные являются объектами (помните, что объект Array - это объект).
Ответ 5
Это похоже на дублированный вопрос, но я всегда использовал что-то вроде этого
var x = new Array(10);
for (var i = 0; i < 10; i++) {
x[i] = new Array(10).fill(false);
}
x[5][5] = true
Кредит: Как создать двумерный массив в JavaScript?
Ответ 6
Поскольку массивы являются ссылочными типами, создание N-мерного массива в JS не так тривиально. Сначала вам нужно создать инструмент клонирования.
Array.prototype.clone = function(){
return this.map(e => Array.isArray(e) ? e.clone() : e);
};
function arrayND(...n){
return n.reduceRight((p,c) => c = (new Array(c)).fill().map(e => Array.isArray(p) ? p.clone() : p ));
}
var arr = arrayND(2,3,4,"x")
console.log(JSON.stringify(arr));
Ответ 7
Функция заполнения, как описано в mdn, копирует одно и то же значение во все индексы массива. Вы можете использовать утилиту ниже для создания клонов массива. Но так как я использую оператор slice, это ограничивается клонированием массивов.
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/fill
if (!Array.prototype.clonefill) {
Object.defineProperty(Array.prototype, 'clonefill', {
value: function(value) {
// Steps 1-2.
if (this == null) {
throw new TypeError('this is null or not defined');
}
var O = Object(this);
// Steps 3-5.
var len = O.length >>> 0;
// Steps 6-7.
var start = arguments[1];
var relativeStart = start >> 0;
// Step 8.
var k = relativeStart < 0 ?
Math.max(len + relativeStart, 0) :
Math.min(relativeStart, len);
// Steps 9-10.
var end = arguments[2];
var relativeEnd = end === undefined ?
len : end >> 0;
// Step 11.
var final = relativeEnd < 0 ?
Math.max(len + relativeEnd, 0) :
Math.min(relativeEnd, len);
// Step 12.
while (k < final) {
O[k] = value.slice(0);
k++;
}
// Step 13.
return O;
}
});
}
Array(100).clonefill(Array(100))
a[0][0] = true
a[1][0]
false