Most of the tutorials that I've read on arrays in JavaScript (including w3schools and devguru) suggest that you can initialize an array with a certain length by passing an integer to the Array constructor using the var test = new Array(4); syntax.
After using this syntax liberally in my js files, I ran one of the files through jsLint, and it freaked out:
Error: Problem at line 1 character 22: Expected ')' and instead saw '4'.
var test = new Array(4);
Problem at line 1 character 23: Expected ';' and instead saw ')'.
var test = new Array(4);
Problem at line 1 character 23: Expected an identifier and instead saw ')'.
After reading through jsLint's explanation of its behavior, it looks like jsLint doesn't really like the new Array() syntax, and instead prefers [] when declaring arrays.
So I have a couple questions:
First, why? Am I running any risk by using the new Array() syntax instead? Are there browser incompatibilities that I should be aware of?
And second, if I switch to the square bracket syntax, is there any way to declare an array and set its length all on one line, or do I have to do something like this:
var test = [];
test.length = 4;
Array(5) gives you an array with length 5 but no values, hence you can't iterate over it.
Array.apply(null, Array(5)).map(function () {}) gives you an array with length 5 and undefined as values, now it can be iterated over.
Array.apply(null, Array(5)).map(function (x, i) { return i; }) gives you an array with length 5 and values 0,1,2,3,4.
Array(5).forEach(alert) does nothing, Array.apply(null, Array(5)).forEach(alert) gives you 5 alerts
ES6 gives us Array.from so now you can also use Array.from(Array(5)).forEach(alert)
If you want to initialize with a certain value, these are good to knows...
Array.from('abcde'), Array.from('x'.repeat(5))
or Array.from({length: 5}, (v, i) => i) // gives [0, 1, 2, 3, 4]
With ES2015 .fill() you can now simply do:
// `n` is the size you want to initialize your array
// `0` is what the array will be filled with (can be any other value)
Array(n).fill(0)
Which is a lot more concise than Array.apply(0, new Array(n)).map(i => value)
It is possible to drop the 0 in .fill() and run without arguments, which will fill the array with undefined. (However, this will fail in Typescript)
Why do you want to initialize the length? Theoretically there is no need for this. It can even result in confusing behavior, because all tests that use the length to find out whether an array is empty or not will report that the array is not empty.
Some tests show that setting the initial length of large arrays can be more efficient if the array is filled afterwards, but the performance gain (if any) seem to differ from browser to browser.
jsLint does not like new Array() because the constructer is ambiguous.
new Array(4);
creates an empty array of length 4. But
new Array('4');
creates an array containing the value '4'.
Regarding your comment: In JS you don't need to initialize the length of the array. It grows dynamically. You can just store the length in some variable, e.g.
var data = [];
var length = 5; // user defined length
for(var i = 0; i < length; i++) {
data.push(createSomeObject());
}
[...Array(6)].map(x => 0);
// [0, 0, 0, 0, 0, 0]
OR
Array(6).fill(0);
// [0, 0, 0, 0, 0, 0]
Note: you can't loop empty slots i.e. Array(4).forEach(() => …)
OR
( typescript safe )
Array(6).fill(null).map((_, i) => i);
// [0, 1, 2, 3, 4, 5]
OR
Classic method using a function ( works in any browser )
function NewArray(size) {
var x = [];
for (var i = 0; i < size; ++i) {
x[i] = i;
}
return x;
}
var a = NewArray(10);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Creating nested arrays
When creating a 2D array with the fill intuitively should create new instances. But what actually going to happen is the same array will be stored as a reference.
var a = Array(3).fill([6]);
// [ [6], [6], [6] ]
a[0].push(9);
// [ [6, 9], [6, 9], [6, 9] ]
Solution
var a = [...Array(3)].map(x => []);
a[0].push(4, 2);
// [ [4, 2], [], [] ]
So a 3x2 Array will look something like this:
[...Array(3)].map(x => Array(2).fill(0));
// [ [0, 0], [0, 0], [0, 0] ]
N-dimensional array
function NArray(...dimensions) {
var index = 0;
function NArrayRec(dims) {
var first = dims[0], next = dims.slice().splice(1);
if(dims.length > 1)
return Array(dims[0]).fill(null).map((x, i) => NArrayRec(next ));
return Array(dims[0]).fill(null).map((x, i) => (index++));
}
return NArrayRec(dimensions);
}
var arr = NArray(3, 2, 4);
// [ [ [ 0, 1, 2, 3 ] , [ 4, 5, 6, 7] ],
// [ [ 8, 9, 10, 11] , [ 12, 13, 14, 15] ],
// [ [ 16, 17, 18, 19] , [ 20, 21, 22, 23] ] ]
Initialize a chessboard
var Chessboard = [...Array(8)].map((x, j) => {
return Array(8).fill(null).map((y, i) => {
return `${String.fromCharCode(65 + i)}${8 - j}`;
});
});
// [ [A8, B8, C8, D8, E8, F8, G8, H8],
// [A7, B7, C7, D7, E7, F7, G7, H7],
// [A6, B6, C6, D6, E6, F6, G6, H6],
// [A5, B5, C5, D5, E5, F5, G5, H5],
// [A4, B4, C4, D4, E4, F4, G4, H4],
// [A3, B3, C3, D3, E3, F3, G3, H3],
// [A2, B2, C2, D2, E2, F2, G2, H2],
// [A1, B1, C1, D1, E1, F1, G1, H1] ]
Math filled values
handy little method overload when working with math
function NewArray( size , method, linear )
{
method = method || ( i => i );
linear = linear || false;
var x = [];
for( var i = 0; i < size; ++i )
x[ i ] = method( linear ? i / (size-1) : i );
return x;
}
NewArray( 4 );
// [ 0, 1, 2, 3 ]
NewArray( 4, Math.sin );
// [ 0, 0.841, 0.909, 0.141 ]
NewArray( 4, Math.sin, true );
// [ 0, 0.327, 0.618, 0.841 ]
var pow2 = ( x ) => x * x;
NewArray( 4, pow2 );
// [ 0, 1, 4, 9 ]
NewArray( 4, pow2, true );
// [ 0, 0.111, 0.444, 1 ]
The shortest:
let arr = [...Array(10)];
console.log(arr);
ES6 introduces Array.from which lets you create an Array from any "array-like" or iterables objects:
Array.from({length: 10}, (x, i) => i);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In this case {length: 10} represents the minimal definition of an "array-like" object: an empty object with just a length property defined.
Array.from allows for a second argument to map over the resulting array.
Sparse arrays are here! 🥳 [2021]
In modern JS engines, sparse arrays are fully supported. You can use [] or new Array(len) in any way you like, even with random access. Dictionary mode seems to be a thing of the past.
In current Chrome (and I guess any V8 environment), Arrays can have a length of up to 2^32-1 and allocation is sparse (meaning empty chunks don't use up any memory):
However, there is a catch
On the one hand, for loops work as intended, however, Array's builtin higher order functions (such as map, filter, find, some etc.) ignore unassigned elements. They require fill (or some other method of population) first:
const a = new Array(10);
const b = new Array(10).fill(0);
a.forEach(x => console.log(x)); // does nothing
b.forEach(x => console.log(x)); // works as intended
Old Version
(I removed most of the old version.) The gist was that creating a large array using new Array(largeNumber) or random accessing an array in places that have not yet been allocated would tumble it into "dictionary mode". Meaning you are using an array with indexes, but under the hood it would use a dictionary to store the values, thus messing with performance, and also with iteration behavior. Luckily that is a thing of the past.
This will initialize the length property to 4:
var x = [,,,,];
I'm surprised there hasn't been a functional solution suggested that allows you to set the length in one line. The following is based on UnderscoreJS:
var test = _.map(_.range(4), function () { return undefined; });
console.log(test.length);
For reasons mentioned above, I'd avoid doing this unless I wanted to initialize the array to a specific value. It's interesting to note there are other libraries that implement range including Lo-dash and Lazy, which may have different performance characteristics.
Here is another solution
var arr = Array.apply( null, { length: 4 } );
arr; // [undefined, undefined, undefined, undefined] (in Chrome)
arr.length; // 4
The first argument of apply() is a this object binding, which we don't care about here, so we set it to null.
Array.apply(..) is calling the Array(..) function and spreading out the { length: 3 } object value as its arguments.
Please people don't give up your old habits just yet.
There is a large difference in speed between allocating memory once then working with the entries in that array (as of old), and allocating it many times as an array grows (which is inevitably what the system does under the hood with other suggested methods).
None of this matters of course, until you want to do something cool with larger arrays. Then it does.
Seeing as there still seems to be no option in JS at the moment to set the initial capacity of an array, I use the following...
var newArrayWithSize = function(size) {
this.standard = this.standard||[];
for (var add = size-this.standard.length; add>0; add--) {
this.standard.push(undefined);// or whatever
}
return this.standard.slice(0,size);
}
There are tradeoffs involved:
This method takes as long as the others for the first call to the function, but very little time for later calls (unless asking for a bigger array).
The standard array does permanently reserve as much space as the largest array you have asked for.
But if it fits with what you're doing there can be a payoff.
Informal timing puts
for (var n=10000;n>0;n--) {var b = newArrayWithSize(10000);b[0]=0;}
at pretty speedy (about 50ms for the 10000 given that with n=1000000 it took about 5 seconds), and
for (var n=10000;n>0;n--) {
var b = [];for (var add=10000;add>0;add--) {
b.push(undefined);
}
}
at well over a minute (about 90 sec for the 10000 on the same chrome console, or about 2000 times slower).
That won't just be the allocation, but also the 10000 pushes, for loop, etc..
(this was probably better as a comment, but got too long)
So, after reading this I was curious if pre-allocating was actually faster, because in theory it should be. However, this blog gave some tips advising against it http://www.html5rocks.com/en/tutorials/speed/v8/.
So still being unsure, I put it to the test. And as it turns out it seems to in fact be slower.
var time = Date.now();
var temp = [];
for(var i=0;i<100000;i++){
temp[i]=i;
}
console.log(Date.now()-time);
var time = Date.now();
var temp2 = new Array(100000);
for(var i=0;i<100000;i++){
temp2[i] = i;
}
console.log(Date.now()-time);
This code yields the following after a few casual runs:
$ node main.js
9
16
$ node main.js
8
14
$ node main.js
7
20
$ node main.js
9
14
$ node main.js
9
19
var arr=[];
arr[5]=0;
alert("length="+arr.length); // gives 6
The simplest form is to use
Array.from({ length: 3 });
// gives you
[undefined, undefined, undefined]
Unlike Array(3) which will give you an array you can't iterate over. Array.from({ length }) gives you an array you can iterate easily.
Array.from({ length: 3 }).map((e, idx) => `hi ${idx}`);
// ['hi 1', 'hi 2', 'hi 3']
Assuming that Array's length is constant. In Javascript, This is what we do:
const intialArray = new Array(specify the value);
The array constructor has an ambiguous syntax, and JSLint just hurts your feelings after all.
Also, your example code is broken, the second var statement will raise a SyntaxError. You're setting the property length of the array test, so there's no need for another var.
As far as your options go, array.length is the only "clean" one. Question is, why do you need to set the size in the first place? Try to refactor your code to get rid of that dependency.
In addition to the answers of others, another clever way is to use Float32Array to create an array and iterate on it.
For this purpose, create an instance from Float32Array with your desired length like this:
new Float32Array(5)
This code returns an array-like that you can convert it to an array with Array.from():
Array.from(new Float32Array(5)) // [0, 0, 0, 0, 0]
You can also use fill() to change the value of items:
Array.from(new Float32Array(5).fill(2)) // [2, 2, 2, 2, 2]
And of course you can iterate on it:
Array.from(new Float32Array(5)).map(item => /* ... */ )
In most answers it is recommended to fill the array because otherwise "you can't iterate over it", but this is not true. You can iterate an empty array, just not with forEach. While loops, for of loops and for i loops work fine.
const count = Array(5);
Does not work.
console.log('---for each loop:---');
count.forEach((empty, index) => {
console.log(`counting ${index}`);
});
These work:
console.log('---for of loop:---');
for (let [index, empty] of count.entries()) {
console.log(`counting for of loop ${index}`);
}
console.log('---for i loop:---');
for (let i = 0, il = count.length; i < il; ++i) {
console.log(`counting for i loop ${i}`);
}
console.log('---while loop:---');
let index = 0;
while (index < count.length) {
console.log(`counting while loop ${index}`);
index++;
}
Check this fiddle with the above examples.
Also angulars *ngFor works fine with an empty array:
<li *ngFor="let empty of count; let i = index" [ngClass]="
<span>Counting with *ngFor {{i}}</span>
</li>
You can set the array length by using array.length = youValue
So it would be
var myArray = [];
myArray.length = yourValue;
The reason you shouldn't use new Array is demonstrated by this code:
var Array = function () {};
var x = new Array(4);
alert(x.length); // undefined...
Some other code could mess with the Array variable. I know it's a bit far fetched that anyone would write such code, but still...
Also, as Felix King said, the interface is a little inconsistent, and could lead to some very difficult-to-track-down bugs.
If you wanted an array with length = x, filled with undefined (as new Array(x) would do), you could do this:
var x = 4;
var myArray = [];
myArray[x - 1] = undefined;
alert(myArray.length); // 4
Related
It's always tricky to think Array.concat thing. Often, I just want to use mutable Array.push because I simply add extra-data on the immutable data. So, I usually do:
array[array.length] = newData;
I've asked a question related got some answers here: How to store data of a functional chain
const L = (a) => {
const m = a => (m.list ? m.list : m.list = [])
.push(a) && m;
//use `concat` and refactor needed instead of `push`
//that is not immutable
return m(a); // Object construction!
};
console.log(L);
console.log(L(2));
console.log(L(1)(2)(3))
some outputs:
{ [Function: m] list: [ 2 ] }
{ [Function: m] list: [ 1, 2, 3 ] }
I feel that push should be replaced with using concat, but still, push makes the code elegant simply because we don't want to prepare another object here.
Basically, I want to do:
arr1 = arr1.concat(arr2);
but, is there any way to write
arr1[arr1.length] = arr2;
which ends up with a nested array, and does not work.
You could assign a new array with a default array for not given m.list.
const L = (a) => {
const m = a => (m.list = (m.list || []).concat(a), m);
return m(a);
};
console.log(L.list);
console.log(L(2).list);
console.log(L(1)(2)(3).list);
You can use multiple parameters in Array.push so:
var a = [];
a.push(3, 4) // a is now [3, 4]
Combined with the ES6 spread syntax:
var a = [1, 2];
var b = [3, 4]
a.push(...b); // a is now [1, 2, 3, 4]
arr1[arr1.length] represents a single value, the value at index arr1.length.
Imagine this array
[ 1 , 2 , 3 , 4 ] // arr of length 4
^0 ^1 ^2 ^3 // indexes
If we say arr1[arr1.length] = someThing
We ask javascript to put something right here, and only here, at index 4:
[ 1 , 2 , 3 , 4 , ] // arr of length 4
^0 ^1 ^2 ^3 ^4 // add someThing in index 4
So, if we want to add something strictly with arr1[arr1.length], then we need to keep doing that for each index. for each meaning any kind of loop. E.G:
// Not recommended to use
var arr1 = [1,2,3];
var arr2 = [3,4,5];
while (arr2.length){
arr1[arr1.length] = arr2.shift();
}
console.log(arr1); // [1,2,3,3,4,5]
console.log(arr2); // []
But, as you can see, this method, or any similar one, even if optimized, is not the right approach. You need a concatenation.
Since you mention a functional one, which returns the resulting array, you can simply replace the initial array and make use of spread operator:
var arr1 = [1,2,3];
var arr2 = [3,4,5];
console.log(arr1 = [...arr1,...arr2]); // [1,2,3,3,4,5]
I have the following simple array:
my_array = [1, 11, 44, 4]
I want to produce a new array consisting of the difference between these elements, so it would be:
diff_array = [10, 33, 40]
What's the best way of going about this?
You could use Array#reduce for iterating and take the absolute delta for pushing to the result array.
Basically you need array.length - 1 deltas and iteration. In this case 3. Reduce takes, if no start value is given, the first two elements and iterates the wanted length. And while it needs the last value for the delta, the last value is returned.
At the end, the returned value of reduce is discarded, becuase it is not used anymore.
1 11 44 4 values
\ / \ / \ /
10 33 40 Math.abs(delta)
var array = [1, 11, 44, 4],
result = [];
array.reduce(function (a, b) {
result.push(Math.abs(a - b));
return b;
});
console.log(result);
here is a simple solution with a plain old for loop
array = [1, 11, 44, 4]
diff = []
for(var i = 1 ; i < array.length ; i++){
diff.push(Math.abs(array[i] - array[i-1]))
}
basically you loop starting at the second element of the array ,, and subtract from from the prev and pushing to the new array .
use this function, pass it the input array, returns the required array.
function diff(array){
var out = []
for (var i = 0; i < array.length-1; i++) {
out.push(Math.abs(array[i+1]-array[i]))
}
return out;
}
Normally one can do this with .reduce() but just for fun lets get some functional.
var myArray = [1, 11, 44, 4],
diff = a => a.length > 1 ? [Math.abs(a[1]-a[0])].concat(diff(a.slice(1))) : [];
console.log(diff(myArray));
Note: The above code is just for demonstration purposes. In your daily JS life you shouldn't do things like this. Use a whatever loop you like but never use recursion in your JS code. You want to see what i mean? Feed this array.
var myArray = Array(1000000).fill().map(_ => ~~(Math.random()*100+1));
It will beautifully crash your browser's tab. Peah..!
Is it possible to get the difference of an associative array and a regular array in Javascript?
Ex.
array1 = [5, 1, 3];
array2 = [1 => 15, 2 => 20, 3 => 10, 4 => 5, 5 =>50 ];
The difference would be...
diff = [2 => 20, 4=> 5];
I assume your question just had a small typo in your declaration of array2. This is not a big deal.
Anyway, here is a bit of hack, but it gives you what you want:
array1 = [5, 1, 3];
array2 = {1: 15, 2: 20, 3: 10, 4: 5, 5: 50};
var result = {};
for (var i in array2) {
if (array1.indexOf(+i) < 0) {
result[i] = array2[i];
}
}
alert(JSON.stringify(result));
Working example
My hack is the +i in the indexOf call, because the properties of your "associative array" are strings, but your array1 contains numbers. The unary + produces a number from a string. Kind of hackish but it is idiomatic an accepted JavaScript practice.
ADDENDUM
As RobG points out, indexOf is an ES5 method, so if your JavaScript engine is ES3 or below, you will need to implement indexOf on your own. An example of how to do this is at MDN. Alternatively, you can just do the equivalent of indexOf by searching the array on your own.
First of all, your second array should be an object and isn't valid JavaScript, as the first two commenters said. Here it is in object form:
var object = { "1": 15, "2": 20, "3": 10, "4": 5, "5": 50 };
This function achieves your desired result:
function findDiff(arr, obj)
{
var tempObj = clone(obj);
for (var i = 0; i < arr.length; i++)
{
var propId = arr[i];
if (tempObj[propId] !== undefined)
delete tempObj[propId];
}
return tempObj;
}
This function relies on a function called clone, which makes sure obj is copied to tempObj by value rather than reference. This prevents the passed object from being modified:
function clone(obj){
if(obj == null || typeof(obj) != 'object')
return obj;
var temp = obj.constructor(); // changed
for(var key in obj)
temp[key] = clone(obj[key]);
return temp;
}
Just call it like this:
var array = [5, 1, 3];
var object = { "1": 15, "2": 20, "3": 10, "4": 5, "5": 50 };
var diff = findDiff(array, object);
You will need to explain in detail what you expect the result of the operation to be.
One interpretation is to remove members from one array based on the values in another, so given:
array1 = [5, 1, 3];
array2 = [15, 20, 10, 5, 50 ];
You might have a function:
function diff(arr1, arr2) {
// Copy arrays so don't affect originals
var t1 = arr1.slice();
var t2 = arr2.slice();
// sort t1
t1.sort();
// Remove members of arr2 from highest indexes to lowest
var i = t1.length;
while (i--) {
t2.splice(t1[i], 1);
}
return t2;
}
alert(diff(array1, array2)); // 15, 10, 50
Note that arrays are zero indexed and there is no 5th member in array2, so the removed values are 20 and 5 (i.e. members with index 1 and 3 respectively).
Another option would be, to do a JSON.stringify() on your variable and check the leftmost or rightmost character of the resulting string. If it is { or }, you have an associative array / object, if [ or ], it is an array. Which I imagine might be a bit costly, depending on the size of your array, but it would do the job.
However... since there is no such thing as a free lunch, and all animals come in pairs, this is only a reasonable solution, if you have used your variable consequently according to your original definition.If you defined an object, like so: obj = [1,2,3] and then, at a later point, added a value such as obj['w'] = 'ww', a JSON.stringify(obj) would only produce [1,2,3], but if you addressed obj['w'] again, you would still get ww, meaning that the value is not forgotten, they just don't mix. Internally, I would imagine, that javascript keeps two separate variable tables, one for objects and one for arrays, and whichever has been defined first, gets the nod when printed with stringify.
And to confuse things still more, if you define a variable as object first, but then add an array key, aka
obj = {1: 11, 2: 22, 3: 33};
obj[4] = 44;
the new key is automatically cast as a string, thus yielding a result in stringify of
{"1":11, "2": 22, "3": 33, "4": 44} //sans the \", for better readibility
Confusing as hell, but I guess that's the price you pay for a little anarchy and ease of use.
I'm just learning JavaScript and it seems like there are a number of ways to declare arrays.
var myArray = new Array()
var myArray = new Array(3)
var myArray = ["apples", "bananas", "oranges"]
var myArray = [3]
What are their difference, and what are the preferred ways?
According to this website the following two lines are very different:
var badArray = new Array(10); // creates an empty Array that's sized for 10 elements
var goodArray= [10]; // creates an Array with 10 as the first element
As you can see these two lines do two very different things. If you
had wanted to add more than one item then badArray would be
initialized correctly since Javascript would then be smart enough to
know that you were initializing the array instead of stating how many
elements you wanted to add.
Is what the authors trying to say is Array(10) creates an array with precisely 10 elements and [10] creates an array of undefined size with the 0th element being 10? Or what does this mean?
In your first example, you are making a blank array, same as doing var x = []. The 2nd example makes an array of size 3 (with all elements undefined). The 3rd and 4th examples are the same, they both make arrays with those elements.
Be careful when using new Array().
var x = new Array(10); // array of size 10, all elements undefined
var y = new Array(10, 5); // array of size 2: [10, 5]
The preferred way is using the [] syntax.
var x = []; // array of size 0
var y = [10] // array of size 1: [1]
var z = []; // array of size 0
z[2] = 12; // z is now size 3: [undefined, undefined, 12]
The preferred way is to always use the literal syntax with square brackets; its behaviour is predictable for any number of items, unlike Array's. What's more, Array is not a keyword, and although it is not a realistic situation, someone could easily overwrite it:
function Array() { return []; }
alert(Array(1, 2, 3)); // An empty alert box
However, the larger issue is that of consistency. Someone refactoring code could come across this function:
function fetchValue(n) {
var arr = new Array(1, 2, 3);
return arr[n];
}
As it turns out, only fetchValue(0) is ever needed, so the programmer drops the other elements and breaks the code, because it now returns undefined:
var arr = new Array(1);
To declare it:
var myArr = ["apples", "oranges", "bananas"];
To use it:
document.write("In my shopping basket I have " + myArr[0] + ", " + myArr[1] + ", and " + myArr[2]);
There are a number of ways to create arrays.
The traditional way of declaring and initializing an array looks like this:
var a = new Array(5); // declare an array "a", of size 5
a = [0, 0, 0, 0, 0]; // initialize each of the array's elements to 0
Or...
// declare and initialize an array in a single statement
var a = new Array(0, 0, 0, 0, 0);
If you are creating an array whose main feature is it's length, rather than the value of each index, defining an array as var a=Array(length); is appropriate.
eg-
String.prototype.repeat= function(n){
n= n || 1;
return Array(n+1).join(this);
}
You can declare like this
const [alice, bob] = [1, 2]
console.log(alice) // 1
console.log(bob) // 2
I don't know the terminology but I want to get it simpler:
var thingTopic1 =['hello','hallo', ..., 'hej'];
var thingTopic2 =['a','b',...,'c'];
...
var thingTopic999 =['x,'y',...,'?'];
so I want to access the data like thing[para1][para2], is there some ready data structure for it or do I need to create messy function with the things? Please, note that sizes of things differ.
You can have arrays of arrays, and the size of each row can be different.
var matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[0]
];
The variable "matrix" will refer to an array with length 4. The syntax you use to refer to (say) the "5" in the second row is exactly what you suggested:
var theFive = matrix[1][1];
You can "build" a matrix like that incrementally of course.
var matrix = [];
for (var i = 1; i < 10; ++i) {
var row = ~~((i - 1) / 3);
if (!matrix[row]) matrix[row] = [];
matrix[row][(i - 1) % 3] = i;
}
matrix.push([0]);
When you set an integer-indexed "property" of an Array instance, Javascript makes sure that the "length" property of the array is updated. It does not allocate space for "holes" in the array, so if you set element number 200 first, there's still just one thing in the array, even though "length" would be 201.
No, there is no data structure for that, but you can easily accomplish it by combining arrays.
You can create an array that contains arrays, which is called a jagged array:
var thing = [
['hello','hallo','goddag','guten tag','nuqneH','hej'],
['a','b','c','d','e','f','g','h','i','j'],
['x,'y','z']
];
Notice how the inner arrays can have different length, which is where the term "jagged" comes from.
You can take advantages from OOP of ES6 :
class Matrix extends Array {
constructor(...rows) {
if(rows.some( r => !Array.isArray(r)))
throw new TypeError('Constructor accepts only rows as array')
super(...rows)
}
push(...rows) {
if(rows.some( r => !Array.isArray(r)))
throw new TypeError('Push method accepts array(s)')
super.push(...rows)
}
}
Use case 1:
Use case 2 :