Reputation: 238
I would like to find this algorithm for copying a 2 dimensional array reffering to a different heap object. If I have for instance...
var result = [[8,2,5],[3],[8,5,2],[0]];
var resultCopy = copyArray(result);
resultCopy[2][0] = 9;
... then....... alert(result[2][0]);
...... should be 8 and not 9!
What I have is this but it does not work, and I can seem to find the answer anywhere else:
function copyArray(array){
result;
array.length==0?return result;
for(var i=0;i!=array.length;i++){
if(array[i] instanceof Array){
return result.push(copyArray(array[i].slice(0)));
} else {
return result.push(array)
}
}
}
Upvotes: 1
Views: 794
Reputation: 51
If you are lucky enough to have a NetScape browser derivative (FF etc.)
resultCopy = eval ( uneval( result ) );
or
resultCopy = eval ( result . toSource( ) );
otherwise use (this has severe limitations but meets and satisfies the OP conditions):
resultCopy = eval( "[ [" + result . join("], \n[") + "] ]" );
The eval
function is "builtin" hiding the recursive nature of its algorithm.
If re-cursing (ie. recursion) is sacrosanct, the following is deeply religious having no iterative statements and recursing completely until each element is not an array. (ie. recursion occurs while an element is an array or is in an array). Given an array, if it is vacuous, then it's copy will be vacuous array.length < 1 ? [ ]
. If not take an element from the array reducing the array to a smaller one that needs to be processed further. This is the recursive reduction step RAffle ( array . pop( ), arbitArrayCopy ( array ) )
. The new array is filled with the element
that was removed nuRA . push ( ... )
. If the element
happens to be an array then process it further ie. re-curse element instanceof Array ? arbitArrayCopy ( element )
. This algorithm is destructive and the original array is to be unblemished, so restore it: array . push ( element )
.
function arbitArrayCopy ( array ) {
/* copies any nD array structure and primitive array elements but
complex compound object array elements are referenced and not copied */
return array.length < 1 ? [ ] : RAffle ( array . pop( ), arbitArrayCopy ( array ) ) ;
function RAffle ( element, nuRA ) {
nuRA . push ( element instanceof Array ? arbitArrayCopy ( element ) : element ) ;
array . push ( element ) ;
return nuRA
}
}
Test:
data:text/html;charset=utf-8,<html>
<!-- this is a scriple or scURIple which codes generic URI's of arbitrary schema
- javascript: schema specific scriples/scURIples are known as scriplets or bookmarklets -->
<script>
javascript:
function RAcopy ( array ) { return array.length < 1 ? [ ] : RAffle( array . pop( ), RAcopy ( array ) ) ;
function RAffle ( element, nuRA ) {
nuRA . push ( element instanceof Array ? RAcopy ( element ) : element ) ;
array . push ( element ) ; return nuRA
} }
result = [[8,2,5],[3],[8,5,2],[0]];
RAdup = RAcopy ( resultCopy = eval( "[ [" + result . join("], \n[") + "] ]" ) ) ;
resultCopy[2][0] = 9; resultCopy[3] = [10,11,12]; RAdup[1]=[ 42, 33, 24 ]; delete RAdup[3];
alert ( [ "Test environment:\n " + window.navigator.userAgent,
"RAdup =\n" + RAdup . join("], \n[") ,
"resultCopy =\n" + resultCopy . join("], \n[") ,
"result =\n" + result . join("], \n[") ] . join("\n ..................... \n") );
</script></html>
(Caveat: scURIples are polyglot challenged due to the schizo lingua vagaries of the concurrent URI, javascript and HTML syntaxes but convenient for immediate mode address bar drag & drop execution - the symbiotic synergy of their syzygy often succumbs to parasitism - fortunately, here the forces are aligned - in particular the HTML <script>
intentionally includes a javascript:
label to make the script a valid URI scriplet via the javascript: schema/protocol and all this is embedded in the larger URI data: scheme scURIple - so the data: URI scURIple encodes valid HTML which encodes valid javascript which encodes a valid javascript: URI scriplet - things get really sqURIlly when the script generates other scURIples or even itself)
Test results:
Test environment:
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.4) Gecko/2008102920 Firefox/3.0.4
(Splashtop-v1.2.17.0)
.....................
RAdup =
8,2,5],
[42,33,24],
[8,5,2],
[
.....................
resultCopy =
8,2,5],
[3],
[9,5,2],
[10,11,12
.....................
result =
8,2,5],
[3],
[8,5,2],
[0
link: Algorithm for copying 2 dimensional array in javascript recursively
Upvotes: 1
Reputation: 6787
There are several errors in this code:
Missing the var
keyword when declaring result
inside the function. This will create/modify the variable in the global scope;
Invalid inline if syntax (missing :
for else). In this case I would suggest using the normal if
syntax.
You are returning the array inside the for
in all paths. This will make it return the result
variable and stop execution in the first iteration of the loop, resulting in an array with only one element.
Missing [i]
inside else
in your for
statement. You probably want to copy an element from the array, not it entirely.
The function you are looking for is probably this:
function copyArray(array) {
var result = []; // creates an result array inside your function scope
if (array.length == 0)
return result; // return this empty array in case the input array is also empty
for (var i = 0; i != array.length; i++) {
if (array[i] instanceof Array) {
result.push(copyArray(array[i].slice(0))); // call the function recursively if the element is an array
} else {
result.push(array[i]); // copy the element if it is not an array (going to use reference if it's an object)
}
}
return result; // returns the resulting array
}
Keep in mind that this won't copy objects but maintain reference to them. If you want to parse them too, take a look at this question here in StackOverflow: How do I correctly clone a JavaScript object?
Upvotes: 0