var sData= "abcdefghijABCDEFGHIJäß©ÐëØ>½îÿ";
You can see a pattern. It appears to be three sequences of 10 characters each; that is, a 10x3 a matrix.
// column: 0123456789
var sData= "abcdefghij" // row 0 (starts at offset 0)
+"ABCDEFGHIJ" // row 1 (starts at offset 10)
+"äß©ÐëØ>½îÿ" // row 2 (starts at offset 20)
Since each row contains 10 columns, I can calculate the start of any row by multiplying the row index by 10. In general, the formula is
// assumes data is a string, sData and rows have 10 columns
function GetCellValue(y,x) {
nRowStart= y*10;
nOffset = nRowStart+ x;
sElementValue= sData.substr(nOffset,1); // access one element
return( sElementValue );
}
....
// y,x (row, column)
alert( GetCellValue(0,0) ); // displays a
alert( GetCellValue(0,1) ); // displays b
alert( GetCellValue(0,2) ); // displays c
alert( GetCellValue(1,2) ); // displays C
alert( GetCellValue(2,2) ); // displays ©
alert( GetCellValue(0,9) ); // displays j
alert( GetCellValue(1,9) ); // displays J
alert( GetCellValue(2,9) ); // displays ÿ
With the above function, we can access the data string as a 2D array of individual characters. All of that is to show that you can impose a 2D structure on a 1D array by adding a special data-access function. But that's not the normal way to do things in JavaScript.
as2D= new Array(); // an array of "whatever"
as2D[0]= new Array("a","b","c","d","e","f","g","h","i","j" );
as2D[1]= new Array("A","B","C","D","E","F","G","H","I","J" );
as2D[2]= new Array("ä","ß","©","Ð","ë","Ø",">","½","î","ÿ" );
That constructs and populates a three-element array; each element is a 10-element array of strings. Now we can use normal JavaScript accessing syntax like:
alert( as2D[0][0] ); // displays a
alert( as2D[2][2] ); // displays ©
alert( as2D[2][9] ); // displays ÿ
var as2D = [
["a","b","c","d","e","f","g","h","i","j"],
["A","B","C","D","E","F","G","H","I","J"],
["ä","ß","©","Ð","ë","Ø",">","½","î","ÿ"]
];
With that syntax, JavaScript constructs an Array-type variable that is exactly the same as with the
var as2D = new Array();
as2D[0] = new Array();
as2D[0].push( "a" );
as2D[0].push( "b" );
as2D[0].push( "c","d","e","f","g","h","i" );
as2D[0].push( "j" );
as2D.push( new Array( "A","B","C","D","E","F","G","H","I","J" ) );
as2D.push( [ "ä","ß","©","Ð","ë","Ø",">","½","î","ÿ" ] );
Once again, the above creates an Array of Array objects and it works the same as the earlier examples.
var as2D= []; // or: new Array();
as2D.push( ["a","b","c","d","e","f","g","h","i","j"] );
as2D.push( ["A","B","C","D","E","F","G","H","I","J"] );
as2D.push( ["ä","ß","©","Ð","ë","Ø",">","½","î","ÿ"] );
Use the String.split() Method
var sData1= "a,b,c,d,e,f,g,h,i,j";
var sData2= "A,B,C,D,E,F,G,H,I,J";
var sData3= "ä,ß,©,Ð,ë,Ø,>,½,î,ÿ";
var as2D= []; // or: new Array();
as2D[0]= sData1.split(",");
as2D[1]= sData2.split(",");
as2D[2]= sData3.split(",");
The second parameter of the split() method identifies the delimiter character; in this case, we used a comma. There is a useful idiom that will help us in this example: If the delimiter is the empty string (""), then the output is an array of individual characters.
var sData1= "abcdefghij";
var sData2= "ABCDEFGHIJ";
var sData3= "äß©ÐëØ>½îÿ";
var as2D= []; // or: new Array();
as2D[0]= sData1.split("");
as2D[1]= sData2.split("");
as2D[2]= sData3.split("");
...or...
var as2D= [];
as2D[0]= "abcdefghij".split("");
as2D[1]= "ABCDEFGHIJ".split("");
as2D[2]= "äß©ÐëØ>½îÿ".split("");
...or...
var as2D= "abcdefghij,ABCDEFGHIJ,äß©ÐëØ>½îÿ".split(",")
as2D[0]=as2D[0].split("");
as2D[1]=as2D[1].split("");
as2D[2]=as2D[2].split("");
...or even...
var as2D= [
"abcdefghij".split(""),
"ABCDEFGHIJ".split(""),
"äß©ÐëØ>½îÿ".split("")
];
That last option kind of surprised me. Coming from C++, I tend to expect that an array that is declared and populated in source code must be fully defined at compile time. But JavaScript is different: that
var declaration is just another piece of procedural code that gets executed at runtime.
for ( var y=0; y<3; y++ ) {
for ( var x=0; x<10; x++ ) {
// do something with myArray[y][x]
}
}
That is, step through each row and in each row step through each column to access the data at that row and column. For instance, this code...
var sOut="<table border=2>";
for (var y=0; y<as2D.length; y++ ) { // for each row
sOut += "<tr>";
for (var x=0; x<as2D[y].length; x++ ) { // for each clm
sOut += "<td>" + as2D[y][x] + "</td>";
}
sOut += "</tr>";
}
sOut += "</table>";
... generates HTML that looks like this:
var nClmsPerRow= as2D[0].length; // assume same length
for ( var x=0; x<nClmsPerRow; x++ ) { // for each row
sOut += "<tr>";
for ( var y=0; y<as2D.length; y++ ) { // for each clm
sOut += "<td>" + as2D[y][x] + "</td>";
}
sOut += "</tr>";
}
...and you can output a table as 10 rows of three columns.
for ( y in as2D ) {
for ( x in as2D[y] ) {
// do something with as2D[y][x];
}
}
The real value of
for...in comes when you have a
sparse array ; that is, when some of the elements are undefined. For instance:
var aSparse= new Array;
aSparse[0]= ["zero", "one", "two" ];
aSparse[4]= [ , "forty-one", ];
aSparse[5]= ["fifty", "fifty-one", "fifty-two"];
for ( y in aSparse ) {
for ( x in aSparse[y] ) {
alert("y,x=(" +y+ "," +x+ ") value: " + aSparse[y][x] );
}
}
...will skip rows 1-3, and the columns 0 and 2 of row 4 -- the elements that have not been populated. It will output:
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (2)
Commented:
An excellent read IMHO! You have my Yes vote above.
One of the most interesting parts for me is how the JavaScript equivalent to "for ... in" (foreach loop) differs from that of Java (and I guess even other languages to think of it) where "for (y in as2D)" would result in y being the actual element (1D array stored at each index in this case) of the collection as2D. But even with just returning the index, the shorthand is definitely useful.
Thanks for another nice DanRollins article to add to collection of good reads.
Regards,
Kevin
Commented:
x = [
[],
[],
[]
]
notation