Javascript array.push replaces all elements instead of adding an array - javascript

I was just trying stuff out in Vanilla JS and ran into a problem where array.push does not push another array (row) whose elems got changed in a for loop, but rather replaces the whole array (mainArr). It would be better to show the code so please scroll below
function genArray(m, n) {
let mainArr = [];
let row = [];
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
row.push(j);
}
mainArr.push(row)
}
return mainArr;
}
let myArr = genArray(3, 2);
console.log(myArr);
/**
* outputs:
*
* [ [ 0, 1, 0, 1, 0, 1 ],
* [ 0, 1, 0, 1, 0, 1 ],
* [ 0, 1, 0, 1, 0, 1 ] ]
*
* why not:
*
* [ [ 0, 1 ],
* [ 0, 1, 0, 1 ],
* [ 0, 1, 0, 1, 0, 1 ] ]
*/
At first I thought it was just because of the reference being appended as this SOF answers says, but as the code shows it doesn't.
let arr1 = []
let arr2 = [1, 2]
arr1.push(arr2)
console.log(arr1); // [ [ 1, 2 ] ]
arr2 = [2, 4]
console.log(arr1); // still [ [ 1, 2 ] ]
let arr3 = []
let obj1 = {name: "John"}
arr3.push(obj1)
console.log(arr3); // [ {name: "John"}]
obj1.name = "Mike"
console.log(arr3); // [ {name: "Mike"} ]

You are updating the same array every time, so all inserted lists will eventually point to the same reference with the value set in the last iteration.
The following is a fix with an enhancement to reach the expected output:
function genArray(m, n) {
const mainArr = [];
for (let i = 0; i < m; i++) {
const row = [];
let count = i;
while(count-- >= 0) {
for (let j = 0; j < n; j++) {
row.push(j);
}
}
mainArr.push(row)
}
return mainArr;
}
console.log( genArray(3, 2) );

You can use Destructuring assignment instead of array.push.
just like this:
function genArray(m, n) {
let mainArr = [];
let row = [];
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
row=[...row,j];
}
mainArr.push(row)
}
return mainArr;
}
let myArr = genArray(3, 2);
console.log(myArr);

Related

I am doing this challenge at Leet Code where you should sort array and delete all zeros and it always keeps one zero?

nums1 = [1,2,3,0,0,0]
nums2 = [2,5,6]
var merge = function(nums1,nums2) {
let deletezeros = function(numi){
for(let i = 0; i < numi.length; i++){
if(numi[i] == 0){
numi.splice(i, 1)
}
}
}
deletezeros(nums1)
deletezeros(nums2)
let result = nums1.concat(nums2)
result.sort()
return result
};
let a = merge(nums1,nums2)
console.log(a)
result is
[
0, 1, 2, 2,
3, 5, 6
]
Decrement i after calling splice:
nums1 = [1, 2, 3, 0, 0, 0]
nums2 = [2, 5, 6]
var merge = function(nums1, nums2) {
let deletezeros = function(numi) {
for (let i = 0; i < numi.length; i++) {
if (numi[i] == 0) {
numi.splice(i, 1)
i--;
}
}
}
deletezeros(nums1)
deletezeros(nums2)
let result = nums1.concat(nums2)
result.sort()
return result
};
let a = merge(nums1, nums2)
console.log(a)

Group items in for loops

Using JavaScript, I am looping through an array of values.
var values = [1, 2, 1, 3, 1, 3, 4, 1]
for (let i = 0; i < values.length; i++) {
console.log(values[i])
}
I want to get the sum for each group of 4. I could do this in multiple for loops by using:
var values = [1, 2, 1, 3]
var sum1 = 0
for (let i = 0; i < values.length; i++) {
sum1 += parseInt(values[i]);
}
var values = [1, 3, 4, 1]
var sum2 = 0
for (let i = 0; i < values.length; i++) {
sum2 += parseInt(values[i]);
}
How can I group by 4 and get the sum of the values for each group by using one for loop?
Can slice() the array and reduce() each sub array
var values = [1, 2, 1, 3, 1, 3, 4, 1]
var sums =[];
for(let i=0; i< values.length; i=i+4){
const subArr= values.slice(i,i+4);
const sum = subArr.reduce((a,c)=>a+c)
sums.push(sum)
}
console.log(sums)
You can use a counter. Reset the counter and sum variable when it reaches the group limit, like below example :
var values = [1, 2, 1, 3, 1, 3, 4, 1];
var result = [];
var counter = 0;
var sum = 0;
for(var i = 0; i < values.length; i++){
counter++;
sum += values[i];
if(counter === 4 || i === values.length-1){
result.push(sum);
counter = 0;
sum = 0;
}
}
console.log(result);
You could take an array as result set and divide the index by 4 and take the integer value for adding the value.
var values = [1, 2, 1, 3, 1, 3, 4, 1],
grouped = values.reduce((r, v, i) => {
var k = Math.floor(i / 4);
r[k] = r[k] || 0;
r[k] += v;
return r;
}, []);
console.log(grouped);

creating an array Javascript breakout game

I'm creating a simple breakout clone using HTML5 Canvas and have come across the loadHitGrid() function, but I'm having difficulty understanding what it does.
It looks like its creating arrays within the hitgrid array
and then filling this with 1's
Can someone help or draw this out?
function loadHitGrid() {
for (var i = 0; i < NUM_ROWS; i++) {
hitGrid[i] = new Array;
for (var j = 0; j < NUM_COLS; j++) {
hitGrid[i][j] = 1;
}
}
}
//Can i replace hitGrid with the following?
hitGrid = [
1, 1, 1, 1, 1, // is this the same as the above????
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1
]
function drawblocks() {
for (var i = 0; i < NUM_ROWS; i++) { // loops trough number of rows
for (var j = 0; j < NUM_COLS; j++) { // loops thgrough number of cols
if (hitGrid[i][j] == 1) { // for each row / col check for 1
ctx.beginPath(); // Satrts a new path used when drawing!
ctx.fillStyle = colours[i];
ctx.fillRect(j * (blockW + SPACING) + SPACING,
i * (blockH + SPACING) + SPACING, blockW, blockH);
}
}
}
This would be :
hitGrid = [[1, 1, 1, 1, 1], // is this the same as the above????
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]];
Of course that means that NUM_ROWS, and NUM_COLUMNS is 5 :)
Check out my comments on the code below:
function loadHitGrid () {
for(var i = 0 ; i < NUM_ROWS ; i ++) {
hitGrid[i] = new Array; //Creating an empty array NUM_ROWS amount of times
for(var j = 0; j < NUM_COLS; j ++) {
hitGrid[i][j] = 1 ; //Populating each newly created empty array with NUM_COLS amount of ones.
}
}
}
So in NUM_ROWS and NUM_COLS both equal 5 and assuming hitGrid was an empty array, the output would look more like:
[[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1]]

How to create multidimensional array for each row?

For a website I used a grid layout. What I want is to store all items per row inside a row.
I have an overall array that is calling arrWrap = [];. Now I want to create for each row an new array, where I store each time 4 items. So a new array should be created after the third item in a row.
How do I achieve this?
I use Javascript for this project.
var arrPos = [];
for (var i = 0; i < elements.length; ++i) {
arrPos[i] = i;
console.dir(arrPos[i]);
if (arrPos[i] > 3) {
alert(arrPos[i]);
};
}
var arrWrap = [];
var steps = 4;
for (var i = 0; i < elements.length; i=i+steps) {
arrWrap.push(elements.slice(i,i+steps));
}
This proposal feature the Array.prototype.reduce and offers two solutions:
Grouped by consecutive elements dataGroupedA
[
[ 0, 1, 2 ],
[ 3, 4, 5 ],
[ 6, 7, 8 ],
[ 9, 10, 11 ],
[ 12, 13, 14 ]
]
Grouped by the 5th element dataGroupedB
[
[ 0, 5, 10 ],
[ 1, 6, 11 ],
[ 2, 7, 12 ],
[ 3, 8, 13 ],
[ 4, 9, 14 ]
]
The calculation of index is the important part. The rest is standard default assignment and pushing the actual element.
var data = Array.apply(Array, { length: 15 }).map(function (_, i) { return i; }),
dataGroupedA = data.reduce(function (r, a, i) {
var index = i / 3 | 0;
r[index] = r[index] || [];
r[index].push(a);
return r;
}, []),
dataGroupedB = data.reduce(function (r, a, i) {
var index = i % 5;
r[index] = r[index] || [];
r[index].push(a);
return r;
}, []);
document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(dataGroupedA, 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(dataGroupedB, 0, 4) + '</pre>');
Please use the following code:
var cIndex= 0;
var data=[];
var cars = ["Saab", "Volvo", "BMW", "a", "v", "c", "q"];
for(var i = 0; i <= 3; i++)
{
cIndex = cIndex + 3;
var row = cars.slice(cIndex -3,cIndex );
data.push(row);
}
console.log(data);

Convert simple array into two-dimensional array (matrix)

Imagine I have an array:
A = Array(1, 2, 3, 4, 5, 6, 7, 8, 9);
And I want it to convert into 2-dimensional array (matrix of N x M), for instance like this:
A = Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9));
Note, that rows and columns of the matrix is changeable.
Something like this?
function listToMatrix(list, elementsPerSubArray) {
var matrix = [], i, k;
for (i = 0, k = -1; i < list.length; i++) {
if (i % elementsPerSubArray === 0) {
k++;
matrix[k] = [];
}
matrix[k].push(list[i]);
}
return matrix;
}
Usage:
var matrix = listToMatrix([1, 2, 3, 4, 4, 5, 6, 7, 8, 9], 3);
// result: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
You can use the Array.prototype.reduce function to do this in one line.
ECMAScript 6 style:
myArr.reduce((rows, key, index) => (index % 3 == 0 ? rows.push([key])
: rows[rows.length-1].push(key)) && rows, []);
"Normal" JavaScript:
myArr.reduce(function (rows, key, index) {
return (index % 3 == 0 ? rows.push([key])
: rows[rows.length-1].push(key)) && rows;
}, []);
You can change the 3 to whatever you want the number of columns to be, or better yet, put it in a reusable function:
ECMAScript 6 style:
const toMatrix = (arr, width) =>
arr.reduce((rows, key, index) => (index % width == 0 ? rows.push([key])
: rows[rows.length-1].push(key)) && rows, []);
"Normal" JavaScript:
function toMatrix(arr, width) {
return arr.reduce(function (rows, key, index) {
return (index % width == 0 ? rows.push([key])
: rows[rows.length-1].push(key)) && rows;
}, []);
}
This code is generic no need to worry about size and array, works universally
function TwoDimensional(arr, size)
{
var res = [];
for(var i=0;i < arr.length;i = i+size)
res.push(arr.slice(i,i+size));
return res;
}
Defining empty array.
Iterate according to the size so we will get specified chunk.That's why I am incrementing i with size, because size can be 2,3,4,5,6......
Here, first I am slicing from i to (i+size) and then I am pushing it to empty array res.
Return the two-dimensional array.
The cleanest way I could come up with when stumbling across this myself was the following:
const arrayToMatrix = (array, columns) => Array(Math.ceil(array.length / columns)).fill('').reduce((acc, cur, index) => {
return [...acc, [...array].splice(index * columns, columns)]
}, [])
where usage would be something like
const things = [
'item 1', 'item 2',
'item 1', 'item 2',
'item 1', 'item 2'
]
const result = arrayToMatrix(things, 2)
where result ends up being
[
['item 1', 'item 2'],
['item 1', 'item 2'],
['item 1', 'item 2']
]
How about something like:
var matrixify = function(arr, rows, cols) {
var matrix = [];
if (rows * cols === arr.length) {
for(var i = 0; i < arr.length; i+= cols) {
matrix.push(arr.slice(i, cols + i));
}
}
return matrix;
};
var a = [0, 1, 2, 3, 4, 5, 6, 7];
matrixify(a, 2, 4);
http://jsfiddle.net/andrewwhitaker/ERAUs/
Simply use two for loops:
var rowNum = 3;
var colNum = 3;
var k = 0;
var dest = new Array(rowNum);
for (i=0; i<rowNum; ++i) {
var tmp = new Array(colNum);
for (j=0; j<colNum; ++j) {
tmp[j] = src[k];
k++;
}
dest[i] = tmp;
}
function matrixify( source, count )
{
var matrixified = [];
var tmp;
// iterate through the source array
for( var i = 0; i < source.length; i++ )
{
// use modulous to make sure you have the correct length.
if( i % count == 0 )
{
// if tmp exists, push it to the return array
if( tmp && tmp.length ) matrixified.push(tmp);
// reset the temporary array
tmp = [];
}
// add the current source value to the temp array.
tmp.push(source[i])
}
// return the result
return matrixified;
}
If you want to actually replace an array's internal values, I believe you can call the following:
source.splice(0, source.length, matrixify(source,3));
This a simple way to convert an array to a two-dimensional array.
function twoDarray(arr, totalPerArray) {
let i = 0;
let twoDimension = []; // Store the generated two D array
let tempArr = [...arr]; // Avoid modifying original array
while (i < arr.length) {
let subArray = []; // Store 2D subArray
for (var j = 0; j < totalPerArray; j++) {
if (tempArr.length) subArray.push(tempArr.shift());
}
twoDimension[twoDimension.length] = subArray;
i += totalPerArray;
}
return twoDimension;
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
twoDarray(arr, 3); // [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
function changeDimension(arr, size) {
var arrLen = arr.length;
var newArr = [];
var count=0;
var tempArr = [];
for(var i=0; i<arrLen; i++) {
count++;
tempArr.push(arr[i]);
if (count == size || i == arrLen-1) {
newArr.push(tempArr);
tempArr = [];
count = 0;
}
}
return newArr;
}
changeDimension([0, 1, 2, 3, 4, 5], 4);
function matrixify(array, n, m) {
var result = [];
for (var i = 0; i < n; i++) {
result[i] = array.splice(0, m);
}
return result;
}
a = matrixify(a, 3, 3);
function chunkArrToMultiDimArr(arr, size) {
var newArray = [];
while(arr.length > 0)
{
newArray.push(arr.slice(0, size));
arr = arr.slice(size);
}
return newArray;
}
//example - call function
chunkArrToMultiDimArr(["a", "b", "c", "d"], 2);
you can use push and slice like this
var array = [1,2,3,4,5,6,7,8,9] ;
var newarray = [[],[]] ;
newarray[0].push(array) ;
console.log(newarray[0]) ;
output will be
[[1, 2, 3, 4, 5, 6, 7, 8, 9]]
if you want divide array into 3 array
var array = [1,2,3,4,5,6,7,8,9] ;
var newarray = [[],[]] ;
newarray[0].push(array.slice(0,2)) ;
newarray[1].push(array.slice(3,5)) ;
newarray[2].push(array.slice(6,8)) ;
instead of three lines you can use splice
while(array.length) newarray.push(array.splice(0,3));
const x: any[] = ['abc', 'def', '532', '4ad', 'qwe', 'hf', 'fjgfj'];
// number of columns
const COL = 3;
const matrix = array.reduce((matrix, item, index) => {
if (index % COL === 0) {
matrix.push([]);
}
matrix[matrix.length - 1].push(item);
return matrix;
}, [])
console.log(matrix);
Using the Array grouping proposal (currently stage 3), you can now also do something like the following:
function chunkArray(array, perChunk) {
return Object.values(array.group((_, i) => i / perChunk | 0));
}
See also the MDN documentation for Array.prototype.group().
Simplest way with ES6 using Array.from()
const matrixify = (arr, size) =>
Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
arr.slice(i * size, i * size + size));
const list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] ;
console.log(matrixify(list, 3));
Another stab at it,
Creating an empty matrix (Array of row arrays)
Iterating arr and assigning to matching rows
function arrayToMatrix(arr, wantedRows) {
// create a empty matrix (wantedRows Array of Arrays]
// with arr in scope
return new Array(wantedRows).fill(arr)
// replace with the next row from arr
.map(() => arr.splice(0, wantedRows))
}
// Initialize arr
arr = new Array(16).fill(0).map((val, i) => i)
// call!!
console.log(arrayToMatrix(arr, 4));
// Trying to make it nice
const arrToMat = (arr, wantedRows) => new Array(wantedRows).fill(arr)
.map(() => arr.splice(0, wantedRows))
(like in: this one)
(and: this one from other thread)
MatArray Class?
Extending an Array to add to a prototype, seems useful, it does need some features to complement the Array methods, maybe there is a case for a kind of MatArray Class? also for multidimensional mats and flattening them, maybe, maybe not..
1D Array convert 2D array via rows number:
function twoDimensional(array, row) {
let newArray = [];
let arraySize = Math.floor(array.length / row);
let extraArraySize = array.length % row;
while (array.length) {
if (!!extraArraySize) {
newArray.push(array.splice(0, arraySize + 1));
extraArraySize--;
} else {
newArray.push(array.splice(0, arraySize));
}
}
return newArray;
}
function twoDimensional(array, row) {
let newArray = [];
let arraySize = Math.floor(array.length / row);
let extraArraySize = array.length % row;
while (array.length) {
if (!!extraArraySize) {
newArray.push(array.splice(0, arraySize + 1));
extraArraySize--;
} else {
newArray.push(array.splice(0, arraySize));
}
}
return newArray;
}
console.log(twoDimensional([1,2,3,4,5,6,7,8,9,10,11,12,13,14], 3))
Short answer use:
const gridArray=(a,b)=>{const d=[];return a.forEach((e,f)=>{const
h=Math.floor(f/b);d[h]=d[h]||[],d[h][f%b]=a[f]}),d};
Where:
a: is the array
b: is the number of columns
An awesome repository here .
api : masfufa.js
sample : masfufa.html
According to that sample , the following snippet resolve the issue :
jsdk.getAPI('my');
var A=[1, 2, 3, 4, 5, 6, 7, 8, 9];
var MX=myAPI.getInstance('masfufa',{data:A,dim:'3x3'});
then :
MX.get[0][0] // -> 1 (first)
MX.get[2][2] // ->9 (last)

Categories

Resources