Dynamically create index in two dimensional array - javascript

Having some trouble with this script. It iterates through a two dimensional array and adds each corresponding index together. So basically arr[0][1] + arr[0][2] + arr[0][3] ... arr[1][1] + arr[1][2] + arr[1][3] ...etc.
This first one works fine. So my logic is ok. My problem here is that I can't create the indices dynamically. I don't think a push will work since I'm summing values here.
var cat_stats_week_radar = [[0,0,0,0,0,0,0,0,0,0,0,0,0,0]];
for (var i = 0; i < cat_stats_week.length; i++) {
for (var j = 0; j < cat_stats_week[0].length; j++) {
cat_stats_week_radar[0][j] += +(cat_stats_week[i][j]);
}
}
This one doesn't work, I don't get an error, just a bunch of NaN values.
var cat_stats_week_radar = [[]];
for (var i = 0; i < cat_stats_week.length; i++) {
for (var j = 0; j < cat_stats_week[0].length; j++) {
cat_stats_week_radar[0][j] += +(cat_stats_week[i][j]);
}
}
Here are the arrays I'm working with.
Array to add:
var cat_stats_week = [
[0,0,0,0,0,0,0,1,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0,0,1,0],
[0,0,0,0,0,0,0,0,0,0,0,0,1,0],
[0,0,1,0,0,0,0,0,0,0,0,0,0,0]
];
Resulting array:
var cat_stats_week_radar = [[0, 0, 1, 0, 0, 0, 2, 1, 0, 0, 0, 0, 2, 0]];

You need to initialize it with the right number of zeroes:
var cat_stats_week_radar = [[]];
for (var i = 0; i < cat_stats_week[0].length; i++) {
cat_stats_week_radar[0].push(0);
}
And with Underscore.js:
_.map(_.zip.apply(null, cat_stats_week), function(a) {
return _.reduce(a, function(a, b) {
return a + b
})
});

Related

2D Array loop behaving strangely (FCC)

I'm doing a learning exercise and am trying to understand the following code. I thought I had a handle on arrays and loops, but this one has got me very confused.
The below code:
function zeroArray(m, n)
{
let newArray = [];
let row = [];
for (let i = 0; i < m; i++)
{
for (let j = 0; j < n; j++)
{
row.push(0);
}
newArray.push(row);
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(matrix);
Returns
[ [ 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0 ] ]
However I would have expected it to return
[ [ 0, 0, ],
[ 0, 0, 0, 0, ],
[ 0, 0, 0, 0, 0, 0 ] ]
Given that in each i loop, we are pushing (0) to row[] twice, before pushing row[] into newArray.
This isn't happening though, and in my VSCode debugger it looks as though in each i loop, every existing index of newArray is being updated with the latest version of the row[] array.
Why is this?
1) Start outer loop with i = 1 upto i <= m, so the loop count will be m
for (let i = 1; i <= m; i++) {
2) You should create a new row every time the inner loop start and push row into newArray after the inner loop ends
3) Set inner loop condition as j < n * i
for (let j = 0; j < n * i; j++) {
function zeroArray(m, n) {
let newArray = [];
// const row = [] // (-)
for (let i = 1; i <= m; i++) {
const row = []; // (+)
for (let j = 0; j < n * i; j++) { // (+)
row.push(0);
}
newArray.push(row);
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(matrix);
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }
You need to make a copy of the array when pushing to newArray:
function zeroArray(m, n) {
let newArray = [];
let row = [];
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
row.push(0);
}
newArray.push(row.slice());
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(JSON.stringify(matrix));
Matrix m x n should be m rows and n cols.
So for 3, 2 you expect
[
[0, 0],
[0, 0],
[0, 0],
]
Just declare row inside the first loop:
function zeroArray(m, n) {
const newArray = [];
for (let i = 0; i < m; i++) {
const row = [];
for (let j = 0; j < n; j++) {
row.push(0);
}
newArray.push(row);
}
return newArray;
}
let matrix = zeroArray(3, 2);
console.log(matrix);

JavaScript updating 2d array value

I'm trying to update every element of a 2d array only once. But unexpectedly array item gets update multiple times.
For example:
const s = "ab";
const m = [...Array(s.length).fill([...Array(s.length).fill("")])]
for(let row = 0; row < s.length; row++) {
for (let col = 0; col < s.length; col++) {
console.log(row, col)
m[row][col] += `<${row}${col}>`
}
}
console.log(m)
it should return m = [ [ '<00>', '<01>' ], [ '<10>', '<11>' ] ]
but it returns m = [ [ '<00><10>', '<01><11>' ], [ '<00><10>', '<01><11>' ] ] instead.
Can anyone explain it, please?
Update:
Here I'm looping through each item once, so there should be no
chance of updating the item twice ( two value should not concat here )
Instead of initializing array with specific length. You may just initialize empty array then push the elements. Because if you do + of 2 strings, it may just concatenate it, for example:
console.log("I "+"am");
Full working code:
const s = "ab";
let m = [];
for(let row = 0; row < s.length; row++) {
m.push([]);
for (let col = 0; col < s.length; col++) {
m[row].push(`<${row}${col}>`);
}
}
console.log(m);
The issue is that you are using <${row}${col}>, You should simple use let size=0 and use Array[i][j] = size++; in place of <${row}${col}>
you should use the following way for 2D Arrays
//Create a new 1D array
let myArray = new Array(2);
// Loop to create 2D array using 1D array
for (let i = 0; i < myArray.length; i++) {
myArray[i] = new Array(2);
}
//declare size
let size = 0;
// Loop to initialize 2D array elements.
for (let i = 0; i < 2; i++) {
for (let j = 0; j < 2; j++) {
myArray[i][j] = size++;
}
}
// Loop to display the elements of 2D array.
for (let i = 0; i < 2; i++) {
for (let j = 0; j < 2; j++) {
document.write(myArray[i][j] + " ");
}
document.write("<br>");
}
You don't even need a loop, you can use map instead.
const a = Array(2).fill(null).map(
(_, row) => Array(2).fill(null).map(
(_, col) => `<${row}${col}>`
)
);

Weird bug in Javascript splice method

I have an array which contains "Zeros" and I want to move all of
the "Zeros" to the last indexes of the array.
The expected output is:
[1,2,3,0,0,0,0]
But instead I get:
[1,2,0,3,0,0,0]
let a = [0, 1, 2, 0, 0, 3, 0];
let count = 0;
let len = a.length;
for (i = 0; i < len; i++) {
if (a[i] == 0) {
count = count + 1;
a.splice(i, 1);
}
}
for (j = 0; j < count; j++) {
a.push(0);
}
console.log(a);
When you remove the item from the array all the element shift down by one. When you advance your index (i++), you skip the shifted down item in the array which happens to be successive zero in the array.
Solution: Do the for next loop backward and it'll work.
Because splice changes the length of the array, you could iterate from the end of the array and splice the found value directly to the last index.
With this approach, you need only a single loop.
var a = [0, 1, 2, 0, 0, 3, 0],
i = a.length;
while (i--) {
if (a[i] === 0) {
a.splice(a.length, 0, ...a.splice(i, 1));
}
}
console.log(a);
A shorter approach without splicing - and starting from zero.
var a = [0, 1, 2, 0, 0, 3, 0],
i, j = 0;
for (i = 0; i < a.length; i++) {
if (a[i] !== 0) {
[a[j], a[i]] = [a[i], a[j]]; // swap
j++;
}
}
console.log(a);
You can do it much simpler with Array.prototype.sort():
const array = [0, 1, 2, 0, 0, 3, 0];
const sortedArray = array.sort((a, b) => {
if (a === 0) {
return 1;
}
if (b === 0) {
return -1;
}
return a - b;
});
console.log(sortedArray);
In the for loop when you splice the array the array and it length are changed.
for that you must fix the i in the for loop by subtract 1
i++;
and fix the length by subtract 1 or reget the length again
let a = [0, 1, 2, 0, 0, 3, 0];
let count = 0;
let len = a.length;
for (i = 0; i < len; i++) {
if (a[i] == 0) {
count = count + 1;
a.splice(i, 1);
len = a.length;
i--;
}
}
for (j = 0; j < count; j++) {
a.push(0);
}
console.log(a);
Instead of splicing the Array over and over again, here is a different approach:
let a = [0, 1, 2, 0, 0, 3, 0];
// create some more (random) data
for (let i = a.length; i < 30; ++i)
a[i] = Math.floor(Math.random() * Math.random() * 10);
console.log(""+a);
let i = 0, j = 0, len = a.length;
// move non-0 values to the front
while (i < len) {
if (a[i] !== 0) {
a[j++] = a[i];
}
++i;
}
// fill the end of the list with 0
while (j < len) a[j++] = 0;
console.log(""+a);
You could add i--; and len--; each time you use splice:
let a = [0, 1, 2, 0, 0, 3, 0];
let count = 0;
let len = a.length;
for (i = 0; i < len; i++) {
if (a[i] == 0) {
count = count + 1;
a.splice(i, 1);
i--; len--;
}
}
for (j = 0; j < count; j++) {
a.push(0);
}
console.log(a);
This is because when you splice 1 element, the keys of the array are shifted down by one, so the key of the next element you want to check is the same as the one you just removed. The len is also corrected with len--; because we just removed an element.
While this answer is the correct way of doing this using your original plan, it is kind of a fix. Your problem was that you loop over an array, and that array loses elements during the loop, and generally the right approach in these situations is to loop backward. This way the elements that risks having their key changed during the loop are the elements we already checked.
Note that each call to splice has generally O(n) complexity. There are many ways to instead achieve your desired result an order of magnitude more efficiently with a single O(n) iteration. Here's one:
let a = [0, 1, 2, 0, 0, 3, 0]
for (let i=0, j=0; j<a.length; j++)
if (a[j] && i != j)
[a[i++], a[j]] = [a[j], 0]
console.log(a)

Arrays acting odd

So, I'm working on a javascript application that can solve any size matrix. I'm running into a SUPER weird problem, where my main array only has the value of 0 after a certain point. The input should be a data set, like this
1, 8
2, 10
3, 13
4, 17
5, 22
But I'm having trouble with it. When I run the code, the console.log prints out a pretty derpy array
[[1, 1, 1, 8],
[0, 0, 0, 0],
[0, 0, 0, 0]]
It gets even weirder. If I move the console.log to before I call the rref function, I get the same thing.
Anybody ever seen this before? Anyone know how to fix it? Thanks!
//Matrix object
var matrix = {
startingDataSet: [],
degree: 0,
M: []
}
//splits up user input into a more readable format
function getDataFromString(data) {
var points = data.split("\n");
for (var i=0; i<points.length; i++) {
points[i] = points[i].split(", ");
points[i][0] = parseInt(points[i][0]);
points[i][1] = parseInt(points[i][1]);
}
return points;
}
//finds the degree of the polynomail from the matrix object's data
function setPolynomialDegree(original) {
var data = original;
console.log(original);
//temporary data set to hold numbers in
var tempNumbers = [];
var degree = 1;
//move the original set of Y values into the temporary data set
for (var i = 0; i < data.length; i++) {
tempNumbers.push(data[i][1]);
}
//while the numbers in tempdata are not the same, execute subtraction
while (tempNumbers[0] != tempNumbers[1]) {
var newnums = []
var l = tempNumbers.length;
//find the difference for every set of numbers (0 & 1, 1 & 2, 2 & 3, etc.), and push those into the new data set
for (var i = 0; i < l - 1; i++) {
newnums.push(tempNumbers[i + 1] - tempNumbers[i]);
}
//replace old data set with new one
tempNumbers = newnums;
//increase polynomial degree by one
degree += 1;
}
return degree;
}
//add 2 arrays together
function addrows(r1, r2) {
var temprow = [];
for (var i = 0; i < r1.length; i++) {
temprow.push(r1[i] + r2[i]);
}
return temprow;
}
//multiply array by constant
function multrow(r1, num) {
var temprow = [];
for (var i = 0; i < r1.length; i++) {
temprow.push(r1[i] * num);
}
return temprow;
}
//rref function
function rref(mtrx, deg) {
var temp1 = [];
var temp2 = [];
for (var row = 0; row < mtrx.length; row++) {
for (var j = 0; j < mtrx.length-1; j++) {
temp1 = multrow(mtrx[row], mtrx[j+1][row]);
temp2 = multrow(mtrx[j+1], mtrx[row][row]);
temp1 = multrow(temp1, -1);
mtrx[j+1] = addrows(temp1, temp2);
}
}
return mtrx;
}
//Main function that will solve the matrix
function solveFromDataSet(data) {
data = getDataFromString(data);
for (var i=0; i<data.length; i++) {
matrix['startingDataSet'].push(data[i]);
}
matrix.degree = setPolynomialDegree(matrix.startingDataSet);
matrix.M = [];
for (var i = 0; i < matrix.degree; i++) {
var row = [];
for (var j = matrix.degree; j > 0; j--) {
row.push(Math.pow(data[i][0], j - 1));
}
row.push(data[i][1]);
matrix['M'][i] = row;
}
var var_array = rref(matrix['M']);
console.log(matrix.M);
return matrix.M;
}

java script array assignation mistake

var UserBoard = new Array(20,20);
for(var i = 0; i < 21; ++i){
for(var j = 0; j < 21; ++j){
UserBoard[i,j] = 0;
}
}
document.write(UserBoard[3,5]);
UserBoard[4,5]=1;
document.write(UserBoard[3,5]);
http://jsfiddle.net/XbyqN/2/
it's quite simple but I don't know why does this. Alert should be 0, not 1 since I've initialized the 2d array to 0.
Can someone explain me why?
Let's break it down
var UserBoard = new Array(20,20);
You are creating an array with two slots, both of them containing the value "20" (int). So your array is [20, 20]
Next, your loop :
for(var i = 0; i < 21; ++i){
for(var j = 0; j < 21; ++j){
UserBoard[i,j] = 0;
}
}
Two dimensional arrays are not defined like this. In that case, only the "j" counter does something. The "i" is simply ignored. So you end up with an array as follow : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Next, the assignement :
UserBoard[4,5]=1;
Is equivalent to :
UserBoard[5]=1;
And your alert :
alert("test: " + UserBoard[3,5]);
Is equivalent to :
alert("test: " + UserBoard[5]);
That's why you get "1" as alert.
If you want two dimensional arrays, you should use the following notation :
UserBoard[4][5] = 1;
Read it all here on MDN : https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array
You want UserBoard[i][j] instead of UserBoard[i,j].
Multidimensional arrays don't work as you seem to think they work. They're, in fact, arrays of arrays.
Use this :
var UserBoard = new Array(20);
for(var i = 0; i < 20; ++i){
UserBoard[i] = new Array(20);
for(var j = 0; j < 20; ++j){
UserBoard[i][j] = 0;
}
}
I suggest you start using console.log and Chrome's developer tool to debug your code (or Firebug). Try this at the end of your code and then type the F12 key :
console.log(UserBoard);
The comma operator evaluates both of its operands (from left to right) and returns the value of the second operand.
var UserBoard = new Array(20,20); // [20, 20]
for(var i = 0; i < 21; ++i){
for(var j = 0; j < 21; ++j){
UserBoard[i,j] = 0; // UserBoard[j] = 0
}
}
UserBoard[4,5]=1; // UserBoard[5] = 1
alert("test: " + UserBoard[3,5]); // UserBoard[5]
What you want is:
var UserBoard = [];
for (var i = 0; i < 20; i++) { // i < 20
UserBoard[i] = [];
for (var j = 0; j < 20; j++) {
UserBoard[i][j] = 0;
}
}
UserBoard[4][5]=1;
alert("test: " + UserBoard[3][5]);
When creating a new array using the array constructor (new Array), the arguments have different meanings, depending on the type and total number of arguments.
var array20long = new Array(20);// = [undefined,undefined,undefined,....].length === 20
var arrayString = new Array('foo');// = ['foo']
var yourArray = new Array(20,20);// = [20,20]
Put simply: passing 1 integer to the array constructor, creates an array with length equal to the int passed, passing several integers will result in 1, 1 dimensional array with a length equal to the total number of argumens. In your case, two integers creating an array with 2 values. Each index will be initialized to its corresponding argument. In your case: index 0 === 20, index 1 === 20, if you had written new Array(20,10), the result would be an array like [20,10].
You get the basic idea.It is important to note that accessing multi dimensional arrays using a comma won't work: instead of writing arr[1,2] you should have written arr[1][2]. Google some introductory tutorials to JavaScript, it won't hurt... and you'll soon learn why using the array constructor isn't the best way of creating arrays

Categories

Resources