Создать копию многомерного массива, а не ссылки - JavaScript
Возможный дубликат:
Каков наиболее эффективный способ клонирования объекта JavaScript?
Это также называют "глубоким копированием", на котором я нашел некоторые статьи. Ближе всего выглядит этот, но для jQuery - я пытаюсь сделать это без библиотеки.
Я также видел в двух местах, что можно сделать что-то вроде:
arr2 = JSON.decode(JSON.encode(arr1));
Но это, по-видимому, неэффективно. Также возможно циклическое и копирование каждого значения по отдельности и повторение всех массивов. Это кажется утомительным и неэффективным.
Итак, какой самый эффективный, небиблиотечный способ копирования многомерного массива JavaScript [[a],[b],[c]]
? При необходимости я полностью доволен методом "не IE".
Спасибо!
Ответы
Ответ 1
Так как это похоже на то, что вы имеете дело с массивом массивов на неизвестном уровне глубины, но вам нужно только иметь дело с ними на одном уровне глубоко в любой момент времени, тогда он будет простым и быстрым в использовании .slice()
.
var newArray = [];
for (var i = 0; i < currentArray.length; i++)
newArray[i] = currentArray[i].slice();
Или используя .map()
вместо цикла for
:
var newArray = currentArray.map(function(arr) {
return arr.slice();
});
Итак, это итерация текущего массива и построение нового массива мелких копий вложенных массивов. Затем, когда вы переходите на следующий уровень глубины, вы сделали бы то же самое.
Конечно, если есть смесь массивов и других данных, вы захотите проверить, что это до того, как вы нарезаете.
Ответ 2
Я не уверен, насколько лучше JSON.stringy
и JSON.parse
, чем encode
и decode
, но вы можете попробовать:
JSON.parse(JSON.stringify(array));
Что-то еще я нашел (хотя я бы немного его изменил):
http://www.xenoveritas.org/blog/xeno/the-correct-way-to-clone-javascript-arrays
function deepCopy(obj) {
if (typeof obj == 'object') {
if (isArray(obj)) {
var l = obj.length;
var r = new Array(l);
for (var i = 0; i < l; i++) {
r[i] = deepCopy(obj[i]);
}
return r;
} else {
var r = {};
r.prototype = obj.prototype;
for (var k in obj) {
r[k] = deepCopy(obj[k]);
}
return r;
}
}
return obj;
}
Ответ 3
Как вы просили повысить производительность, я думаю, вы также поделитесь с не общим решением. Чтобы скопировать многомерный массив с известным количеством уровней, вы должны пойти с самым простым решением, некоторые вложенные для-петли. Для вашего двухмерного массива это будет выглядеть примерно так:
var len = arr.length,
copy = new Array(len); // boost in Safari
for (var i=0; i<len; ++i)
copy[i] = arr[i].slice(0);
Нативный метод slice
более эффективен, чем пользовательский для цикла, но он не создает глубокие копии, поэтому мы можем используйте его только на самом низком уровне.
Ответ 4
Любой рекурсивный алгоритм, который не посещает один и тот же node дважды, будет примерно таким же эффективным, как и с javascript (по крайней мере в браузере) - в некоторых ситуациях на других языках вы можете уйти с копированием патронов памяти, но javascript явно не обладает этой способностью.
Я предлагаю найти кого-то, кто уже сделал это, и используя их реализацию, чтобы убедиться, что вы правильно поняли - это нужно только определить один раз.