I am trying to add array of arrays dynamically in javascript. I need the data in the following format -
var dataArray = [[],[],[],.....,[]];
How can I initialize this kind of array? Suppose if I have three arrays to be added, I can initialize as follows -
var dataArray = [[],[],[]];
This will accept only three records to be added. But, what should I do in case of adding large number of arrays? Here I cannot know the amount of data I get as input.
I have tried using concat() and merge() methods, these are adding contents directly in to a single array, but that is not what I wanted.
Can any one please help me out on this?
You can build or add an array into an array like this:
var dataArray = [];
dataArray.push([1,2,3]);
dataArray.push([3,4,5]);
console.log(dataArray); // [[1,2,3], [3,4,5]]
Or, if you want to add elements to the sub-arrays:
var dataArray = [];
dataArray.push([1,2,3]);
dataArray.push([3,4,5]);
dataArray[0].push(4);
dataArray[1].push(9);
console.log(dataArray); // [[1,2,3,4], [3,4,5,9]]
You initialize a sub-array by assigning an array to the element of the outer array. You can then use array operations directly on the sub-array element:
// create a sub-array element
dataArray[2] = [];
dataArray[2].push(8);
dataArray[2].push(7);
console.log(dataArray[2]); // [8,7]
console.log(dataArray); // [[1,2,3,4], [3,4,5,9], [8,7]]
The key thing it appears you don't understand is that an array of arrays is just that. It's an outer array where each element in the outer array is itself an array. You use ordinary array methods to operate on either the outer array or the inner arrays. To operate on an inner array, you fetch that element from the outer array and then just treat it as an array. For example:
var dataArray = [];
dataArray.push([1,2,3]);
dataArray.push([3,4,5]);
console.log(dataArray); // [[1,2,3], [3,4,5]]
var innerArray = dataArray[0];
console.log(innerArray); // [1,2,3]
innerArray.push(12);
console.log(innerArray); // [1,2,3,12]
innerArray.legnth = 2;
console.log(innerArray); // [1,2]
innerArray.push(9,8,7);
console.log(innerArray); // [1,2,9,8,7]
innerArray.splice(1,2);
console.log(innerArray); // [1,8,7]
You have wrote "I am trying to add array of arrays dynamically in javascript"
The simple way is using Array.prototype.push method:
var arr1 = [1,2], arr2 = [3,4], arr3 = [5,6], arr4 = [7,8], arr5 = [9,10],
dataArray = [];
[].push.apply(dataArray, [arr1, arr2, arr3, arr4, arr5]);
console.log(JSON.stringify(dataArray, 0, 4));
The console.log output:
[
[
1,
2
],
[
3,
4
],
[
5,
6
],
[
7,
8
],
[
9,
10
]
]
There are tons of way you can do this. A simple one could be
var arrayN = n => Array(n).fill([])
document.write("<pre>" + JSON.stringify(arrayN(10)) + "</pre>")
On another thinking if you already have arrays of arrays then the most simplified way of concatenating them in place should be using the new spread operator like;
var arr = [[1,2,3],[1,3,5]],
brr = [[3,2,1],[7,8,9]];
arr.push(...brr);
document.write("<pre>" + JSON.stringify(arr) + "</pre>");
Related
I face something I don't understand with an array. Indeed, I created an array I have filled with empty subArrays to obtain a 2D Matrix.
But when I manipulate the array it doesn't behave as I expected.
var arr = new Array(5);
arr.fill([]);
arr[2].push("third rank item");
console.log(arr);
//[ [ 'third rank item' ],
// [ 'third rank item' ],
// [ 'third rank item' ],
// [ 'third rank item' ],
// [ 'third rank item' ] ]
Every lights on this matter will be welcomed
This is the same old problem with arrays (and objects in general) being references rather than values.
Specifically, when you do arr.fill([]), you are taking that one single empty array and using that to fill the parent one.
It's like saying:
var arr = new Array(5);
arr[0] = arr[1] = arr[2] = arr[3] = arr[4] = [];
They all refer to the same array! So when you then go on to modify one of them, it looks like they're all modified (but really it's still the same one)
Unfortunately there's no simple way to assign an empty array to each one. You could do something like:
Array.apply(null, Array(5)).map(function() {return [];});
Essentially, create an (initialised) empty array of length 5 and map each (empty) value to a new [].
EDIT: Seems like I'm stuck in old times. As per #torazaburo's comment, you can use Array.from instead of Array.apply(null, Array(5)).map, like so:
Array.from( new Array(5), function() { return []; } );
As you can notice using array.fill you're filling the array with a reference to the same array,
if you want to instantiate each array index to an empty array a normal while loop will do:
var arr = [];
var n = 5
while(n--)
arr[n] = []
arr[2].push("third rank item");
console.log(arr);
Option 2:
if you have lodash package available, you can also use _.map as this is specificaly designed to loop through a sparse array (native map will skip non init values)
var arr =_.map(new Array(5), (x => []))
arr[2].push("third rank item");
console.log(arr)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
The eleventh line of the ECMA doc of Array.prototype.fill is clearly giving the reason for the mystery.
Repeat, while k < final
Let Pk be ToString(k).
Let setStatus be Set(O, Pk, value, true).
ReturnIfAbrupt(setStatus).
Increase k by 1.
Here "value" is just a reference received. And they are setting it as a property to array directly. That means all the filled arrays are just reference to a single array object.
It's happens cause of reference. Array is a type of object and object works on their references when you fill your array with [] or new Array() fill run only ones and put the same array in all indexes that's why when you update an sub-array all are updated.
Solution:
let arr = new Array(5).fill(0).map(ele => ele = []);
arr[2].push("something");
OR
let arr = Array.of([], [], [], []);
arr[2].push("something");
Result: as expected only 2 index of arr is updated.
With ES6 I recommend this method to create 2 or multidimensional arrays:
// create an M x N dimension grid and fill it with 0's
const myArray = [...Array(M)].map(r => [...Array(N)].map(r => 0));
Try this ,this is quick solution for you in one line.
var arr = new Array(5);
arr = Array.from(arr, x => []);
arr[2].push("third rank item");
console.log(arr);
You can try this,
var arr = new Array(5);
var i = 0;
while (i < arr.length)
arr.fill([], i++);
arr[2].push("third rank item");
console.log(arr);
A bit different:
let array= JSON.parse(JSON.stringify(new Array(N).fill([])));
or
let array=new Array(N).fill(null).map(()=>[]);
All the answers were correct and reasonable and so I decided to just try it out on my Chrome console. So the answer to the OP is that this is happening because you cannot do a direct fill.
If I understand part of the question is why can't you just do:
const grid = Array(5).fill([])
which is saying okay we have a structure like this:
//[ [ ],
// [ ],
// [ ],
// [ ],
// [ ] ]
And then you are saying go and fill the third one like so:
grid[2].push("third rank item");
But instead of seeing the third one filled with that string, you see all of them. It's simple, you are creating one single array and throwing it in at every location inside of grid. In memory there is only one inner array so you threw that string into that array, it would affect every index.
But I found some behavior slightly different than what I had expected.
If you write the following:
const grid = Array(3).fill([false, false, false]);
You would get the following:
(3) [Array(3), Array(3), Array(3)]
(3) [false, false, false]
(3) [false, false, false]
(3) [false, false, false]
Then if you run: grid[0].push(true), you will get the following:
(3) [Array(4), Array(4), Array(4)]
(4) [false, false, false, true]
(4) [false, false, false, true]
(4) [false, false, false, true]
So modifying one, modifies all, so that's why you cant just do a direct fill and then push as you did, instead you have to do the map() statement like so:
const grid = Array(3)
.fill(null)
.map(() => Array(3).fill(false));
And that will run the inner function three times and each time we generate a brand new and different array.
var array1 = ["james","bob"];
var array2 = ["name","age"];
i had created let us say two arrays array1 and array2. what i'm doing is now for every element in array1 i want a new array of length 5 for that. for example for "james" i want an array of length 5 and for "bob" i want array if length 5 only. Also array1 is dynamic, not static. How to achieve that?
You can use array#reduce. Reduce will iterate for each name in your array1 and you have aggregator newarr where code will keep inserting an array of 5 elements using newarr.push(Array(5))(Array(5) is a constructor to create an array of 5 elements);
In case you want to give default value you can use array#fill()
var array1 = ["james","bob"];
var newarr = array1.reduce((newarr, name) => {
newarr.push(Array(5));
return newarr;
},[]);
console.log(newarr);
Say you have an array-like Javascript ES6 Iterable that you know in advance will be finite in length, what's the best way to convert that to a Javascript Array?
The reason for doing so is that many js libraries such as underscore and lodash only support Arrays, so if you wish to use any of their functions on an Iterable, it must first be converted to an Array.
In python you can just use the list() function. Is there an equivalent in ES6?
You can use Array.from or spread syntax (...).
Example:
const x = new Set([ 1, 2, 3, 4 ]);
const y = Array.from(x);
console.log(y); // = [ 1, 2, 3, 4 ]
const z = [ ...x ];
console.log(z); // = [ 1, 2, 3, 4 ]
Summary:
Array.from() function, it takes an iterable as in input and returns an array of the iterable.
Spread syntax: ... in combination with an array literal.
const map = new Map([[ 1, 'one' ],[ 2, 'two' ]]);
const newArr1 = [ ...map ]; // create an Array literal and use the spread syntax on it
const newArr2 = Array.from( map ); //
console.log(newArr1, newArr2);
Caveat when copying arrays:
Be cognizant of the fact that via these methods above only a shallow copy is created when we want to copy an array. An example will clarify the potential issue:
let arr = [1, 2, ['a', 'b']];
let newArr = [ ...arr ];
console.log(newArr);
arr[2][0] = 'change';
console.log(newArr);
Here because of the nested array the reference is copied and no new array is created. Therefore if we mutate the inner array of the old array, this change will be reflected in the new array (because they refer to the same array, the reference was copied).
Solution for caveat:
We can resolve the issue of having shallow copies by creating a deep clone of the array using JSON.parse(JSON.stringify(array)). For example:
let arr = [1, 2, ['a', 'b']]
let newArr = Array.from(arr);
let deepCloneArr = JSON.parse(JSON.stringify(arr));
arr[2][0] = 'change';
console.log(newArr, deepCloneArr)
You can use the Array.from method, which is being added in ES6, but only supports arrays and iterable objects like Maps and Sets (also coming in ES6). For regular objects, you can use Underscore's toArray method or lodash's toArray method, since both libraries actually have great support for objects, not just arrays. If you are already using underscore or lodash, then luckily they can handle the problem for you, alongside adding various functional concepts like map and reduce for your objects.
The following approach is tested for Maps:
const MyMap = new Map([
['a', 1],
['b', 2],
['c', 3]
]);
const MyArray = [...MyMap].map(item => {
return {[item[0]]: item[1]}
});
console.info( MyArray ); //[{"a", 1}, {"b", 2}, {"c": 3}]
<Your_Array> = [].concat.apply([], Array.from( <Your_IterableIterator> ));
You could also do the following, but both approaches are certainly not recommendable (merely a proof-of-concept for completeness):
let arr = [];
for (let elem of gen(...)){
arr.push(elem);
}
Or "the hard way" using ES5 + generator function (Fiddle works in current Firefox):
var squares = function* (n) {
for (var i = 0; i < n; i++) {
yield i * i;
}
};
var arr = [];
var gen = squares(10);
var g;
while (true) {
g = gen.next();
if (g.done) {
break;
}
arr.push(g.value);
}
I am trying to make a copy of a javascript array and modify the 'copy' without modifying the original variable too, can anyone explain what I am doing wrong..
e.g
var array1 = [2, 5];
var array2 = '';
array2 = array1;
array2.pop();
console.log(array1);
console.log(array2);
// both output the same, however I want it to show array1 with 1 single item
I am trying to make it so array2 will only contain the one item in the array & array1 will contain two items in the array. Any ideas what I'm doing wrong?
In order to create a copy of an array rather than assign the reference value you can use the .slice method.
array2 = array1.slice(0);
Slice returns a (shallow) copy of the given array from the given index to the (optional end index)
Use slice() to copy the array.
var array1 = [2, 5];
var array2 = '';
array2 = array1.slice(0);
array2.pop();
console.log(array1);
console.log(array2);
slice does not alter the original array, but returns a new "one level
deep" copy that contains copies of the elements sliced from the
original array.
Documentation
It is as simple as using the slice function:
var array1 = [2, 5];
var array2 = '';
array2 = array1.slice();
array2.pop();
console.log(array1);
console.log(array2);
Here you are telling javascript to get a copy of the elements in array1 and assign the result to array2. By not setting the start and ending position it will slice the whole array.
When you writing this
array2 = array1 //It creates reference on array1 object
array2.pop() // removes 5 from both end
So you have to clone one array to another by slice() method---
array2 = array1.slice(0) // cloning array1 's element to array2
array2.pop() // removes 5 from only array2 not from array1
Now it works fine
Alter the line array2 = array1; to:
array2 = array1.slice(0);
Slice method returns a (shallow) copy of the given array from the given index to the (optional end index)
I hope this helps.
I have programmed in Microsoft Small Basic in the past, which can have arrays like this:
Array[1][1] = "Hello"
Array[1][2] = "Hi"
Array[1][2] = "Hey"
Now, in Javascript, I know how to create a single array (var Array = New Array()) but are there any array types like the ones above?
There are no true multidimensional arrays in JavaScript. But you can create an array of arrays like you have done.
JavaScript's arrays are just objects with a special length property and a different prototype chain.
Yes, you need to create an array of arrays:
var x = new Array(3);
x[0] = new Array(3);
x[1] = new Array(3);
x[2] = new Array(3);
x[0][0] = "Hello";
etc.
Remember that indexing is zero-based.
Edit
Or:
var x=[];
x[0] = [];
x[1] = [];
x[2] = [];
...
x[0][0] = "Hello";
etc.
You can achieve this:
var o = [[1,2,3],[4,5,6]];
Also you can use the fact that objects in javascript are dictionaries:
var o;
o["0"] = {'0':1, '1':2, '1':3};
var x = o["0"]["1"]; //returns 2
The easiest way would be to just declare an array, and initialize it with a bunch of other arrays. For example:
var mArray = [
[1,2,3],
[4,5,6]
];
window.alert(mArray[1][1]); //Displays 5
As others have pointed out, this is not actually a multi-dimentional array in the standard sense. It's just an array that happens to contain other arrays. You could just as easily have an array that had 3 other arrays, an int, a string, a function, and an object. JavaScript is cool like that.
You can create arrays statically in JS like this:
var arr = [
[1, 2, 3, 4],
[8, 6, 7, 8]
];
Note that since this is not a true "multidimentional array", just an "array of arrays" the "inner arrays" do not have to be the same length, or even the same type. Like so:
var arr = [
[1, 2, 3, 4],
["a", "b"]
];