1

I am basically looking for a general function copy(array) that will return identical n-dimensional array without any references to the former one.

Paul
  • 139,544
  • 27
  • 275
  • 264
Ognjen
  • 2,508
  • 2
  • 31
  • 47
  • none... but don't judge me, i am beginner in javascript. i've only looked at this: http://stackoverflow.com/questions/419858/how-to-deep-copy-an-irregular-2d-array, and it wasn't general enough for my case. – Ognjen Jun 08 '12 at 00:35
  • 1
    @Ognjen - Java is not JavaScript. – Derek 朕會功夫 Jun 08 '12 at 00:36
  • btw i am porting some code from java to js, if you wonder why i needed this :) – Ognjen Jun 08 '12 at 00:36
  • Do you have to have an arbitrary copy of any types? If you know the types and dimensions of the array, the problem is a lot easier. – jfriend00 Jun 08 '12 at 00:37
  • Um, what do you mean by "deep copy"? Can you do it like this: `var new_array = old_array;` – Derek 朕會功夫 Jun 08 '12 at 00:37
  • @Ognjen: That linked question is on Java, not on JavaScript. Search for "javascript object copy clone" – Bergi Jun 08 '12 at 00:37
  • @Derek, they want a real copy, not a reference. – jfriend00 Jun 08 '12 at 00:38
  • @jfriend00 - I see `deep copy` many times, but I still don't get what is the difference between those two... Can you explain it to me? – Derek 朕會功夫 Jun 08 '12 at 00:39
  • Nevermind, found [this](http://blog.imaginea.com/deep-copy-in-javascript/). – Derek 朕會功夫 Jun 08 '12 at 00:43
  • 1
    @Derek - A shallow copy makes a copy of the top level items, but if there are any items deeper than that (e.g. arrays in arrays or arrays in a property), it does not make a copy of those (they end up being references to the same objects). A deep copy makes sure that every item at every level is a copy. A deep copy usually uses recursion. – jfriend00 Jun 08 '12 at 00:44
  • @Derek: sorry, i accidentally pasted the wrong link! btw. thanks for the quick answers! – Ognjen Jun 08 '12 at 00:45

4 Answers4

5

This works for arrays, it won't work for nested objects (that aren't Arrays):

function copy(arr){
    var new_arr = arr.slice(0);
    for(var i = new_arr.length; i--;)
        if(new_arr[i] instanceof Array)
            new_arr[i] = copy(new_arr[i]);
    return new_arr;
}

Use it like this:

var arr = [
   [[1,2,3],[75]], 100,
   [[[1]]], [],
   [1,[2,[3],4],5], 6, 7, 8
];

var new_arr = copy(arr);
Paul
  • 139,544
  • 27
  • 275
  • 264
1

Using jQuery (works for arrays and "plain" objects):

var a = [[1,[2,3]],[4]];
var b = $.extend(true, [], a);
a[0][0] = 42;             // modify object in a
alert(JSON.stringify(b)); // [[1,[2,3]],[4]]

Or JSON direct (if all objects are JSON-izable):

var a = [[1,[2,3]],[4]];
var b = JSON.parse(JSON.stringify(a))
a[0][0] = 42;             // modify object in a
alert(JSON.stringify(b)); // [[1,[2,3]],[4]]

Older versions of IE (8? 7?) will need a shim for the JSON object.

Paul
  • 139,544
  • 27
  • 275
  • 264
0

I just wanted to add to Paulpro's answer. Note that this is identical to his answer except that I changed copy(new_arr[i]) to copy(arr[i]), and new_arr.length to arr.length.

function copy(arr){
var new_arr = arr.slice(0);
for(var i = arr.length; i--;)
    if(new_arr[i] instanceof Array)
        new_arr[i] = copy(arr[i]);
return new_arr;
}

The reason copy(new_arr[i]) worked is because the .slice copied over what arr[i] was pointing at, making them equal.

Also, while Paulpro's answer works for all cases, if by chance each member of each dimension of the multi-dimensional array is either an array or a non-array you can make it more efficient by only slicing non-array dimensions. I mean what is the point of copying over an array of pointers that will simply be overwritten by the following recursion?

function copy(arr){
if(arr[0] instanceof Array){
    var new_arr = new Array(arr.length);
    for(var i = arr.length; i--;)
        new_arr[i] = copy(arr[i]);
}
else{var new_arr = arr.slice(0);}
return new_arr;
}
user3015682
  • 1,215
  • 12
  • 13
0

This is my solution to clone a multidimensional array; Actually i had to invent Array.prototype.clone() in order to invent a function to generate N dimension array and initialize it with a value.

Array.prototype.clone = function(){
  return this.reduce((p,c,i) => (p[i] = Array.isArray(c) ? c.clone() : c, p),[])
}

function arrayND(...n){
  return n.reduceRight((p,c) => c = (new Array(c)).fill(true).map(e => Array.isArray(p) ? p.clone() : p ));
}

var arr = arrayND(...[4,4,4],8); //last argument is the initializing value
arr[0][1][3] = "eight";
console.log(JSON.stringify(arr));
Redu
  • 25,060
  • 6
  • 56
  • 76