So I hacked this code from somewhere else, but have an object variable to store x,y values in an array every time a hex is clicked, defined with two functions, one to add an element and one to remove the last element
var objMoves = {
length: 0,
addElem: function addElem(elem) {
// obj.length is automatically incremented
// every time an element is added.
[].push.call(this, elem);
},
removeElem: function removeElem(last) {
// this removes the last item in the array
[].splice.call(this,last, 1);
}
};
I call it like this:
objMoves.addElem({ x: hexX, y: hexY });
Result if I dump the objMoves into the console log is "{"0":{"x":2,"y":1},"length":1}"
However, what I really want is something like
objMoves.addElem({ x: hexX, y: hexY },stackID:"abcdef");
So the result would be something like
{stackId:"abcdef",moves:[{"x":2,"y":1},{"x":3,"y":4}]}
{stackId:"xyz",moves:[{"x":5,"y":2},{"x":6,"y":2},{"x":7,"y":2}]}
etc, where the inner array gets added to for a given stackID. I think I need to nest the objects?
push() is for arrays, not objects, so use the right data structure.
var objMoves = [];
// ...
data[0] = { "": "", "": "" };
data[1] = { ....};
// ...
var tempData = [];
for ( var index=0; index<data.length; index++ ) {
if ( data[index].objMoves ) {
tempData.push( data );
}
}
data = tempData;
or deal with it like it is an object. while Objects does not support push property, you can save it as well using the index as key.
It sounds like what you're looking for is something like this:
var objMoves = {
addElem: function(id, elem) {
var obj = this[id] || {
stackId: id,
moves: []
};
obj.moves.push(elem);
this[id] = obj;
},
removeElem: function(id, last) {
this[id].moves.splice(last, 1);
}
}
objMoves.addElem("abcdef", {x: 123, y: 456});
objMoves.addElem("xyz", {x: 1, y: 2});
objMoves.addElem("abcdef", {x: 100, y: 50});
console.log(objMoves);
The functions take a stack ID as a parameter, so they can use that as a key into the object to find the sub-object with that ID. The moves are stored in an array in that sub-object.
I was a little bit fascinated from the code, that you have taken from the MDN JavaScript reference site. It shows us how we could use an object as an array. And so I wrote some functions to do it.
Solution with all, what you need:
var objMoves =
{
// objMoves.length is automatically incremented every time an element is added
length: 0,
//add an object to new(with stackId) or given(by stackId) array element
addElem: function(object, stackId)
{
var index = this.getElemIndex(stackId);
if(index > -1)
this[index].moves.push(object);
else
[].push.call(this, {stackId: stackId, moves: [object]})
},
//remove the array element on lastElemIndex
removeElem: function(lastElemIndex)
{
[].splice.call(this, lastElemIndex, 1)
},
//remove the object on lastElemIndex from the array element with stackId
removeMovesElem: function(stackId, lastElemIndex)
{
var index = this.getElemIndex(stackId);
if(index > -1)
this[index].moves.splice(lastElemIndex, 1)
},
//get the array element index by stackId
getElemIndex: function(stackId)
{
for(var i = this.length; i--;)
if(this[i].stackId == stackId)
return i
return -1
}
};
//we check functions:
objMoves.addElem({x: 2, y: 1}, 'abcdef');
objMoves.addElem({x: 3, y: 4}, 'abcdef');
objMoves.addElem({x: 5, y: 2}, 'xyz');
objMoves.addElem({x: 6, y: 2}, 'xyz');
objMoves.addElem({x: 7, y: 2}, 'xyz');
console.log(JSON.stringify(objMoves, null, '\t'));
console.log('===========================');
var index = objMoves.getElemIndex('abcdef');
objMoves.removeElem(index);
console.log(JSON.stringify(objMoves, null, '\t'));
console.log('===========================');
objMoves.removeMovesElem('xyz', 1);
console.log(JSON.stringify(objMoves, null, '\t'));
I want to create such array in loop
dataset: [
{
x: 0,
y: 0,
},
{
x: 1,
y: 0.993,
}
]
But this way is not correct.
var array = new Array(10);
for (var i = 0; i < 5; ++i) {
array[i].x = 1;
array[i].y = 2;
}
How I can initialize in correct way?
The comments made by SLaks and squint are correct, so this answer is more of an explanation of why your code isn't working like you think it should, and an example of what you could do instead.
You created an array with room to hold 10 things but you didn't specify what those things were and so nothing is contained in the array.
var array = new Array(10);
you can visualize your array like this:
array = [undefined, undefined, undefined, undefined,...
The array you created was just a container for 10 things not yet defined. When you tried to assign the 'x' and 'y' properties of the array elements, you were were trying to operate on something that did not exist. To get what you want, I suggest creating an object that has the properties you want, with initial values, and then use your loop to add the number of elements you want.
var array = [];
var arrayObject = {x:0,y:0};
for(i=0; i < 10; i++){
array.push(arrayObject);
}
You can do this job in one assignment line as follows;
var dataSet = (new Array(10)).fill("initial y value").reduce((p,c,i) => p.concat({x:i,y:c}),[]);
console.log(dataSet);
I just couldn't figure what y values you would like to have so inserted the initial values of the array. Change them the way you like later. I hope it helps.
Replace the new Array(10) with
var array = Array.apply( {}, { length: 10 } ).map( function() { return {} });
new Array(10) is creating an array like
[ undefined, undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined]
So you are trying to assign x on undefined
If you tried
new Array(10).map(function(){ return {}; }) it will not work either.
An es6 way to do it would be
Array.from(new Array(10), () => { return { x: 1, y: 2 }; })
In JavaScript the Array acts different than in static-typed languages, so there's no need to initialize it with fixed length.
For ECMAScript 6 specification and later:
var points = [].fill.call({ length: 5 }, {x: 1, y: 1});
It produces
[{x: 1, y: 1},
{x: 1, y: 1},
{x: 1, y: 1},
{x: 1, y: 1},
{x: 1, y: 1}]
To ensure old browsers' support use for loop:
var points = [{x: 1, y: 1}];
for (var i = 0; i < 5; i++) points.push(points[0]);
Using Javascript, I am trying to convert some JSON data into the format used in Highcharts' basic line chart.
What I have to start with:
originalArray = [
['valueA', 1],
['valueA', 0],
['valueB', 9],
['valueB', 9],
['valueB', 3],
['valueC', 11]
]
And what I'm trying to create using the above:
desiredArray = [{
name: 'valueA',
data: [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}, {
name: 'valueB',
data: [0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0]
}, {
name: 'valueC',
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
}]
For some additional context, the 0-11 in originalArray[i][1] references a month (0 = January), and the desiredArray is a list of unique names and a count of their occurrences by month.
So far, I can:
Convert the data into a new array of objects
For each unique name in originalArray
Create a new object in the desiredArray, and set the name attribute
Add a data attribute that contains an empty array
But then I run into trouble, and can't figure out how to:
Loop through the originalArray
If the name in the originalArray matches the name in the desiredArray
Increment a counter in the matching seriesArray[i].data array, using the value of originalArray[i][1] as the index (it always be 0-11).
So I'm asking:
What's a good way to iterate across my originalArray, match up unique values, and then act only on those matches to push to the desiredArray.
What's the best way to increment the counters in desiredArray[i].data
I'm open to using libraries, such as underscore.js. Have been trying to figure this out for a couple of days now, so pretty much anything goes within the bounds of Javascript.
Updated with proper array initialization, now.
var max = originalArray.reduce(function(p,c){return Math.max(p,c[1]);},0);
var initSums = function(size) {
var arr = new Array(size);
for (var i=0;i<size;i++)
arr[i]=0;
return arr;
}
var map = originalArray.reduce(function(sums,val){
if (!sums.hasOwnProperty(val[0])) {
sums[val[0]] = initSums(max+1);
}
sums[val[0]][val[1]]++;
return sums;
},{});
var desiredArray = Object.keys(map).map(function(key) {
return {name: key, data: map[key]};
});
What we're doing here is a multi-step process:
Decide how big our arrays are going to need to be, by first scanning for the largest value in the original array.
Use an object to aggregate the counts (using Array.reduce()).
Transform the object and its properties into an array of name/data pair objects (using Array.map).
Edit: An improvement on S McCochran's solution, skipping the extraneous search for the maximum value in originalArray, since there should always be 12 elements of each data array, one per month.
function formatForHighcharts(array) {
// Create a map from value name to array of month counts
var map = originalArray.reduce(function(sums, pair) {
var key = pair[0], val = pair[1];
if(!(key in sums))
sums[key] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
// val is the month index, which corresponds directly to array index, so increase that
sums[key][val]++;
return sums;
}, {});
// Map the object to an array of { name: ..., data: ... } pairs
var formatted = Object.keys(map).map(function (key) {
return { name: key, data: map[key] };
});
return formatted;
}
Usage:
var desiredArray = formatForHighcharts(originalArray);
I want to create a two dimensional array in Javascript where I'm going to store coordinates (x,y). I don't know yet how many pairs of coordinates I will have because they will be dynamically generated by user input.
Example of pre-defined 2d array:
var Arr=[[1,2],[3,4],[5,6]];
I guess I can use the PUSH method to add a new record at the end of the array.
How do I declare an empty two dimensional array so that when I use my first Arr.push() it will be added to the index 0, and every next record written by push will take the next index?
This is probably very easy to do, I'm just a newbie with JS, and I would appreciate if someone could write a short working code snippet that I could examine. Thanks
You can just declare a regular array like so:
var arry = [];
Then when you have a pair of values to add to the array, all you need to do is:
arry.push([value_1, value2]);
And yes, the first time you call arry.push, the pair of values will be placed at index 0.
From the nodejs repl:
> var arry = [];
undefined
> arry.push([1,2]);
1
> arry
[ [ 1, 2 ] ]
> arry.push([2,3]);
2
> arry
[ [ 1, 2 ], [ 2, 3 ] ]
Of course, since javascript is dynamically typed, there will be no type checker enforcing that the array remains 2 dimensional. You will have to make sure to only add pairs of coordinates and not do the following:
> arry.push(100);
3
> arry
[ [ 1, 2 ],
[ 2, 3 ],
100 ]
If you want to initialize along with the creation, you can use fill and map.
const matrix = new Array(5).fill(0).map(() => new Array(4).fill(0));
5 is the number of rows and 4 is the number of columns.
ES6
Matrix m with size 3 rows and 5 columns (remove .fill(0) to not init by zero)
[...Array(3)].map(_=>Array(5).fill(0))
let Array2D = (r,c) => [...Array(r)].map(_=>Array(c).fill(0));
let m = Array2D(3,5);
m[1][0] = 2; // second row, first column
m[2][4] = 8; // last row, last column
// print formated array
console.log(JSON.stringify(m)
.replace(/(\[\[)(.*)(\]\])/g,'[\n [$2]\n]').replace(/],/g,'],\n ')
);
If you want to be able access the matrix like so:
matrix[i][j]
I find it the most convenient to init it in a loop.
var matrix = [],
cols = 3;
//init the grid matrix
for ( var i = 0; i < cols; i++ ) {
matrix[i] = [];
}
This will give you
[ [], [], [] ]
so
matrix[0][0]
matrix[1][0]
returns undefined and not the error "Uncaught TypeError: Cannot set property '0' of undefined".
You can nest one array within another using the shorthand syntax:
var twoDee = [[]];
You can try something like this:-
var arr = new Array([]);
Push data:
arr[0][0] = 'abc xyz';
An empty array is defined by omitting values, like so:
v=[[],[]]
a=[]
b=[1,2]
a.push(b)
b==a[0]
You can fill an array with arrays using a function:
var arr = [];
var rows = 11;
var columns = 12;
fill2DimensionsArray(arr, rows, columns);
function fill2DimensionsArray(arr, rows, columns){
for (var i = 0; i < rows; i++) {
arr.push([0])
for (var j = 0; j < columns; j++) {
arr[i][j] = 0;
}
}
}
The result is:
Array(11)
0:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
3:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
4:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
5:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
6:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
7:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
8:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
9:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
10:(12)[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
One Liner
let m = 3 // rows
let n = 3 // columns
let array2D = Array(m).fill().map(entry => Array(n))
This implementation creates a unique subarray for each entry. So setting array2D[0][1] = 'm' does not set each entry's [1] index to 'm'
I know this is an old thread but I'd like to suggest using an array of objects rather than an array of arrays. I think it make the code simpler to understand and update.
// Use meaningful variable names like 'points',
// anything better than a bad pirate joke, 'arr'!
var points = [];
// Create an object literal, then add it to the array
var point = {x: 0, y: 0};
points.push(point);
// Create and add the object to the array in 1 line
points.push({x:5, y:5});
// Create the object from local variables
var x = 10;
var y = 8;
points.push({x, y});
// Ask the user for a point too
var response = prompt("Please enter a coordinate point. Example: 3,8");
var coords = response.split(",").map(Number);
points.push({x: coords[0], y: coords[1]});
// Show the results
var canvas = document.getElementById('graph');
var painter = canvas.getContext("2d");
var width = canvas.width, height = canvas.height;
var scale = 10, radius = 3.5, deg0 = 0, deg360 = 2 * Math.PI;
painter.beginPath();
for (var point of points) {
var x = point.x * scale + scale;
var y = height - point.y * scale - scale;
painter.moveTo(x + radius, y);
painter.arc(x, y, radius, deg0, deg360);
painter.fillText(`${point.x}, ${point.y}`, x + radius + 1, y + radius + 1);
}
painter.stroke();
<canvas id="graph" width="150" height="150" style="border: 1px solid red;"></canvas>
This one should work:
const arr = new Array(5).fill().map(_ => new Array(5).fill(0)) // ✅
You may ask why did I use map instead of:
const badArr = new Array(5).fill(new Array(5).fill(0)) // ❌
The problem with the example above is that it adds references to the array that was passed into the fill method:
While this one works fine:
const grid = Array.from(Array(3), e => Array(4));
Array.from(arrayLike, mapfn)
mapfn is called, being passed the value undefined, returning new Array(4).
An iterator is created and the next value is repeatedly called. The value returned from next, next().value is undefined. This value, undefined, is then passed to the newly-created array's iterator. Each iteration's value is undefined, which you can see if you log it.
var grid2 = Array.from(Array(3), e => {
console.log(e); // undefined
return Array(4); // a new Array.
});
ES6
const rows = 2;
const columns = 3;
const matrix = [...Array(rows)].map(() => [...Array(columns)].fill(0));
console.log(matrix);
Create an object and push that object into an array
var jSONdataHolder = function(country, lat, lon) {
this.country = country;
this.lat = lat;
this.lon = lon;
}
var jSONholderArr = [];
jSONholderArr.push(new jSONdataHolder("Sweden", "60", "17"));
jSONholderArr.push(new jSONdataHolder("Portugal", "38", "9"));
jSONholderArr.push(new jSONdataHolder("Brazil", "23", "-46"));
var nObj = jSONholderArr.length;
for (var i = 0; i < nObj; i++) {
console.log(jSONholderArr[i].country + "; " + jSONholderArr[i].lat + "; " +
jSONholderArr[i].lon);
}
var arr = [];
var rows = 3;
var columns = 2;
for (var i = 0; i < rows; i++) {
arr.push([]); // creates arrays in arr
}
console.log('elements of arr are arrays:');
console.log(arr);
for (var i = 0; i < rows; i++) {
for (var j = 0; j < columns; j++) {
arr[i][j] = null; // empty 2D array: it doesn't make much sense to do this
}
}
console.log();
console.log('empty 2D array:');
console.log(arr);
for (var i = 0; i < rows; i++) {
for (var j = 0; j < columns; j++) {
arr[i][j] = columns * i + j + 1;
}
}
console.log();
console.log('2D array filled with values:');
console.log(arr);
The most simple way to create an empty matrix is just define it as an empty array:
// Empty data structure
const matrix = []
However, we want to represent something similar to a grid with n and m parameters know ahead then we can use this instead.
// n x m data structure
const createGrid = (n, m) => [...Array(n)].map(() => [...Array(m)].fill(0))
const grid = createGrid(3, 5)
Here is a simple snippet showing how to use them.
const createGrid = (n, m) => [...Array(n)].map(() => [...Array(m)].fill(0))
const toString = m => JSON.stringify(m)
.replace(/(\[\[)(.*)(]])/g, '[\n [$2]\n]')
.replace(/],/g, '],\n ')
// Empty data structure
const matrix = []
console.log(toString(matrix))
matrix.push([1,2,3])
matrix.push([4,5,6])
matrix.push([7,8,9])
console.log(toString(matrix))
// n x m data structure
const grid = createGrid(3, 5)
console.log(toString(grid))
No need to do so much of trouble! Its simple
This will create 2 * 3 matrix of string.
var array=[];
var x = 2, y = 3;
var s = 'abcdefg';
for(var i = 0; i<x; i++){
array[i]=new Array();
for(var j = 0; j<y; j++){
array[i].push(s.charAt(counter++));
}
}
If we don’t use ES2015 and don’t have fill(), just use .apply()
See https://stackoverflow.com/a/47041157/1851492
let Array2D = (r, c, fill) => Array.apply(null, new Array(r))
.map(function() {
return Array.apply(null, new Array(c))
.map(function() {return fill})
})
console.log(JSON.stringify(Array2D(3,4,0)));
console.log(JSON.stringify(Array2D(4,5,1)));
We usually know the number of columns but maybe not rows (records). Here is an example of my solution making use of much of the above here. (For those here more experienced in JS than me - pretty much everone - any code improvement suggestions welcome)
var a_cols = [null,null,null,null,null,null,null,null,null];
var a_rxc = [[a_cols]];
// just checking var arr = a_rxc.length ; //Array.isArray(a_rxc);
// alert ("a_rxc length=" + arr) ; Returned 1
/* Quick test of array to check can assign new rows to a_rxc.
i can be treated as the rows dimension and j the columns*/
for (i=0; i<3; i++) {
for (j=0; j<9; j++) {
a_rxc[i][j] = i*j;
alert ("i=" + i + "j=" + j + " " + a_rxc[i][j] );
}
if (i+1<3) { a_rxc[i+1] = [[a_cols]]; }
}
And if passing this array to the sever the ajax that works for me is
$.post("../ajax/myservercode.php",
{
jqArrArg1 : a_onedimarray,
jqArrArg2 : a_rxc
},
function(){ },"text" )
.done(function(srvresp,status) { $("#id_PageContainer").html(srvresp);} )
.fail(function(jqXHR,status) { alert("jqXHR AJAX error " + jqXHR + ">>" + status );} );
What's wrong with
var arr2 = new Array(10,20);
arr2[0,0] = 5;
arr2[0,1] = 2
console.log("sum is " + (arr2[0,0] + arr2[0,1]))
should read out "sum is 7"
const dp=new Array(3).fill(new Array(3).fill(-1))
It will create below array:
[ [ -1, -1, -1 ], [ -1, -1, -1 ], [ -1, -1, -1 ] ]
You can nest a new array as you fill the first one:
let ROWS = 2,
COLS = 6;
let arr = new Array(ROWS).fill(new Array(COLS).fill(-1));
Output:
arr =
[
[-1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1]
]
If you're confused, lets break this down with declaring/filling 1 array:
Make a new array size d, filled with any initial value
let arr1d = new Array(d).fill(<whatever_fill_val>);
Now, instead of filling your first array with a int/string/etc, you can fill it with ANOTHER array, as you fill the nested one!
let arr = new Array(d).fill(new Array(n).fill(-1));
// for 3 x 5 array
new Array(3).fill(new Array(5).fill(0))