I thought initializing an multi dimensional array would be easy:
row = Array(4).fill(0)
block = Array(4).fill(row)
block[2][2] = 15
but that just creates an array of one row, 4 times, so if I assign block[2][2] = 15, then the whole column is 15.
(4) [Array(4), Array(4), Array(4), Array(4)]
0:(4) [0, 0, 15, 0]
1:(4) [0, 0, 15, 0]
2:(4) [0, 0, 15, 0]
3:(4) [0, 0, 15, 0]
I tried Array(4).fill(Array(4).fill(0)) but had the same result.
You could write a helper function to initialize your two dimensional array. For example:
const grid = (r, c) => Array(r).fill(null).map(r => Array(c).fill(null));
const g = grid(4, 4);
g[2][2] = 15;
console.log(g);
This was actually quite challenging to solve. I much prefer the accepted answer from fubar - however I thought I would add another possibility for some variance.
Pro: Doesn't obfuscate that you are dealing with an Array (like with the accepted answer).
Con: Hard to read.
var row = new Array(4).fill(0)
var block = new Array(4).fill(0).map(v => deepClone(row))
block[2][2] = 15
console.log(block);
function deepClone(array){return JSON.parse(JSON.stringify(array));}
How does this work? Well after you fill the array with blank values, .map is now able to iterate each and replace the value. In this case, it is a hacky deep clone of row thanks to the trusty ole JSON.parse.
Related
Looking for general advice on approaches here. Description and pseudocode below:
Array1 has 100 objects type integer
Array2 has 100 objects type integer
Create Array 3 10,000 objects summing the two arrays
Array3.1 = Array1.[Field1] from 1 to 100 + Array2.1.[Field1]
Array3.2 = Array1.[Field1] from 1 to 100 + Array2.2.[Field1]
Array3.3 = Array1.[Field1] from 1 to 100 + Array2.3.[Field1]
……
Array3.100 = Array1.[Field1] from 1 to 100 + Array2.100.[Field1]
Challenges:
Not sure how to easily reference the field within an object in the array. I can pull up the object line but this returns the entire object whereas I only want to pull one field. This would be helpful beyond this particular question.
Not sure about the best method to create the new array, whether it should be a loop or something else.
Further background
The final objective will be to create an output that compares the sum of the specific field for every pair within the two arrays to find and then rank them from best to worst.
It's not that difficult.
Every entry in the resulting array is just the 2nd array with the value at the current index of the first array added to it.
const a1 = [0, 5, 10, 15, 20];
const a2 = [0, 2, 4, 6, 8];
const result = a1.map(x => a2.map(y => x + y));
console.log(result);
If you don't want the resulting array to nested, use flatMap:
const a1 = [0, 5, 10, 15, 20];
const a2 = [0, 2, 4, 6, 8];
const result = a1.flatMap(x => a2.map(y => x + y));
console.log(result);
If I have a 2d array like this...
var x = [
[0, 1, 2],
[0, 1, 2],
[0, 1, 2]
]
And I want to print it to the console using console.table() but I also want to add column names, how do I do that?
I see in the documentation its really easy when its an array of objects, but when I try to add column names to this 2d array it messes with the array dimensions and does not print correctly.
EDIT:
All of the answers this far have said what I said I already knew, that this was easy to do with an array of objects. My question is, "Is it possible to add column names if you are passing a 2d array."
I tried to console.table with your 2d array compare with array of object, Hope this is what you looking for.
You need to pass an array of objects to console.table() in order for it to display with column names, exammple below using your data:
const arrayOfObjects = new Array(10).fill({
columnOne : 0,
columnTwo: 1,
columnThree: 2
})
console.table(arrayOfObjects)
Here is a screenshot directly from the Developer Tools Console in Chrome.
More info can be found here regarding this function: https://developer.mozilla.org/en-US/docs/Web/API/Console/table
If the array contains objects, then the columns are labeled with the property name.
So you can convert the elements to objects with relevant names as properties.
var x = [
[0, 1, 2],
[0, 1, 2],
[0, 1, 2]
]
function ARR(first, second, third) {
this.first = first;
this.second = second;
this.third = third;
}
let itemArr = x.map( item => new ARR(...item))
console.table(itemArr);
I have a function that needs to take an array from each in a group of documents, and sum each position in each array with it's index 'partner' at the [n]th position.
The arrays look something like this......
[300, 230, 45, 0, 0, 0]
[200, 100, 0, 0, 0, 0]
[2, 1, 0, 0, 0, 0]
...
From which I would want to return [502, 331, 45, 0, 0, 0]. Using this question which is asking almost the same thing, I copied a reduce function, so my function now looks like this...
this.projects.forEach(function (project) {
let arrays = project.yearsTotal
result = arrays.reduce(function (r, a) {
a.forEach(function (b, i) {
r[i] = (r[i] || 0) + b;
});
return r
}, []);
})
However, this tells me that 'a.forEach is not a function', I must admit that I'm not sure exactly what the reduce function is doing, but I think perhaps that it isn't working because my arrays are not an array of arrays, they exist separately.
Javascript tells me they are objects, not arrays, but I'm not sure that is significant. Please could someone tell me how to do this?
The difference with the question you linked seems to be your numeric data, that is stored inside array of objects (in property yearsTotal) - and not in array of arrays of numbers.
If that's the case, you can just create another array storing only the values you need:
const projectYearsTotal = this.projects.map(p => p.yearsTotal);
... and then you can proceed with reduce-forEach-ing it.
Your current solution tries to 'zip-sum' the array of numbers (value of 'yearsTotal' of each individual project), not array of arrays of numbers. Hence forEach is not a function error.
I'm using flot api to draw charts. Look at this chart type HERE.
In that example they've used values like,
var sin = [], cos = [];
for (var i = 0; i < 14; i += 0.5) {
sin.push([i, Math.sin(i)]);
cos.push([i, Math.cos(i)]);
}
Now the chart was drawn "curved" lines, when i replaced the
sin.push([i, Math.sin(i)]);
cos.push([i, Math.cos(i)]);
with,
sin[i]=[i, Math.sin(i)];
cos[i]=[i, Math.cos(i)];
Then the chart gets drawn using straight lines. I've two questions now.
1) What is the difference between the two types of array assignments?
2) Is this because of difference in array assignments or the API behaviour?
any help greatly appreciated! Thanks.
Edit: Set i to increment by 1 and set different values using push method or default assignment, you'll get the same result.
The i is not Integer. You can use only int in array index.
1) What is the difference between the two types of array assignments?
A) None, except the push places next int for index.
2) Is this because of difference in array assignments or the API behaviour?
A) Yes with your way the array is invalid, because the 1.5 value for a key is parsed as a string and api can not read the array as it expect.
Try using apis way or using different values for for statement.
I think there's a problem with i increment. It is clear that on every iteration i is increased by 0.5, not 1. Look:
for (var i = 0; i < 14; i += 0.5)
So sin[i]=... won't work properly. But sin.push(...) will work.
Array indexes can't be fractions and are always strings, so the number 1.5 is being converted to a string '1.5' and the sequence will be '0', '0.5', '1', '1.5' and so on. But using push, all indexes will be integer strings, so will be 0, 1, 2, etc.
No doubt an integer based loop is being used to read the values from the array, so it is skipping the .5 ones (i.e. every second element) and giving jagged edges.
Generally this would work, but in this case you're incrementing i by 0.5 which results in i being a float-value.
Look at the output of both variants:
// push
// cos
[[0, 1],
[0.5, 0.8775825618903728],
[1, 0.5403023058681398],
[1.5, 0.0707372016677029],
[2, -0.4161468365471424],
[2.5, -0.8011436155469337], ...]
// sin
[[0, 0],
[0.5, 0.479425538604203],
[1, 0.8414709848078965],
[1.5, 0.9974949866040544],
[2, 0.9092974268256817],
[2.5, 0.5984721441039564], ...]
// array-index
// cos
[[0, 1],
[1, 0.5403023058681398],
[2, -0.4161468365471424],
[3, -0.9899924966004454],
[4, -0.6536436208636119], ...]
// sin
[[0, 0],
[1, 0.8414709848078965],
[2, 0.9092974268256817],
[3, 0.1411200080598672],
[4, -0.7568024953079282], ...]
Put simply, I want to subtract one array from another.
The arrays are arrays of objects. I understand I can cycle through one array and on each item, comparing values in the other array, but that just seems a little messy.
Thanks for the help, hopefully this question isnt too basic, I have tried googling it with no luck :(
EDIT:
The Objects in the Arrays I wish to remove will have identical values but are NOT the same object (thanks #patrick dw). I am looking to completely remove the subset from the initial array.
This answer is copied from https://stackoverflow.com/a/53092728/7173655, extended with a comment and a solution with objects.
The code filters array A. All values included in B are removed from A.
const A = [1, 4, 3, 2]
const B = [0, 2, 1, 2]
console.log(A.filter(n => !B.includes(n)))
The same with objects:
const A = [{id:1}, {id:4}, {id:3}, {id:2}]
const B = [{id:0}, {id:2}, {id:1}, {id:2}]
console.log(A.filter(a => !B.map(b=>b.id).includes(a.id)))
http://phpjs.org/functions/index
There is no built-in method to do this in JavaScript. If you look at this site there are a lot of functions for arrays with similar syntax to PHP.
http://www.jslab.dk/library/Array
This site has some js functions on "sets"
I think you need the diff function.
It should remove all values from list a, which are present in list b keeping their order.
let a = [0, 2, 5, 6, 1];
let b = [2, 6, 2, 5, 0];
function arrayDiff() {
for (i of b) {
for (j of a) {
if (i === j) {
a.splice(a.indexOf(j), 1);
}
}
}
return a;
}