How to create a 2D array in Javascript - javascript

I'm trying to create a 2D array with javascript that I can ultimately put inside a nested loop to extract X/Y information.
What am I doing wrong here?
function createMatrix(){
let colcount = 0;
let rowcount = 0;
var pixel_array = new Array();
var y_array = new Array();
for (var i = 0; i <= 100; i++){
var checker = (i+1) % 10;
if(checker == 0){
y_array.push(i);
//create new X array
pixel_array[rowcount] = [];
//push column data into row array
pixel_array[rowcount].push(y_array);
//create new Y array
var y_array = new Array();
//increment row counter
//reset column counter
parseInt(rowcount++);
colcount = 0;
}else{
y_array.push(i);
parseInt(colcount++);
}
}
//sanity check: spit out the matrix
for (var x=0; x<10;x++){
for(var y=0; y<10; y++){
console.log(pixel_array[x][y]);
}
}
}
I was expecting to call a specific X/Y 'coordinate' and extract the information from that 'cell'. However, I'm getting an error that basically says the [Y] part of the array is not defined.
Looking at console.log and console.table - I can see the X array is filled, but it isn't like I'd expect, just a list of numbers not another array.
Edit: To be more specific, my goal is to create a 2D array from a single For loop. The nested for loop at the bottom of the code is shown as an example of how I would like to call the 'cells' [X][Y].

This code:
pixel_array[rowcount] = [];
//push column data into row array
pixel_array[rowcount].push(y_array);
creates a new array, stores it in pixel_array[rowcount], and then pushes y_array into it. So at that point, you have an array (pixel_array) with an entry that's an array (the one you created via []), with an entry that's an array (y_array). That's closer to a 3D array than a 2D array.
You may be overcomplicating it a bit. I can't quite make out what you want your final array to be, so here's an example of creating a 3x4 "2D array" (it isn't really¹, it's an array of arrays, but...) with the numbers 1-12 in it, see comments:
// Create the outer array
var array = [];
for (var x = 0; x < 4; ++x) {
// Create the inner array for this row and store it in `array[x]`
var inner = array[x] = [];
for (var y = 0; y < 3; ++y) {
// Set the value of the inner array at `y`,
// which is also `array[x][y]`
inner[y] = (x * 3) + y + 1;
}
}
console.log(array);
.as-console-wrapper {
max-height: 100% !important;
}
In a comment you've said:
I want to create a 2D array from a single For loop. So in my example I'm looping 0-99, with the expected result being a 10x10 'matrix' (0-9, 10-19, 20-29, etc).
Here's an example doing that:
// Create the outer array
var array = [];
var inner;
for (var n = 0; n < 100; ++n) {
// Time to create a new inner array?
if (n % 10 === 0) { // It's important that this condition is true on the first loop iteration
inner = [];
array.push(inner);
}
// Add this `n` to the current inner array
inner.push(n);
}
console.log(array);
.as-console-wrapper {
max-height: 100% !important;
}
¹ "it isn't really, it's an array of arrays" - JavaScript doesn't have multi-dimensional arrays. It has arrays that can contain other arrays. For many purposes, the distinction doesn't really matter, but it means (amongst other things) that the arrays can be jagged: Not all entries in the outer array have to have the same length. (In fact, they don't even have to be arrays.)

Related

When using strings with numbers at the start in an array key (Indesign 2017, extendscript) they don't get added to the array

Observe:
var groupedLinks = new Array;
for(var i = 0; i < 5; i++) {
linkName = "59notgonnawork" + i;
groupedLinks[linkName] = new Array;
}
I would have expected the result to be the array groupedLinks to be filled up with 5 new keys, the value would be 5 empty arrays.
The actual result in extendscript would be ... grouplinks ... empty.
If I would change this example to be:
var groupedLinks = new Array;
for(var i = 0; i < 5; i++) {
linkName = "notgonnawork" + i;
groupedLinks[linkName] = new Array;
}
It would work perfectly. The only change is the missing "59" at the start of the string used for the array key.
Note that this works perfectly when I run it in console for chrome or firefox. It seems to be indesign and/or extendscript fooling around.
Anything have any ideas why ? I've meanwhile worked around the problem but I'm intrigued.
I would have expected the result to be the array groupedLinks to be filled up with 5 new keys, the value would be 5 empty arrays.
That's exactly what it does, but the way you're viewing the data is likely concealing it because you're not using the proper data structure. Also, property access won't work without using [] because identifiers may not start with a number, so you'd need:
groupedLinks["59notgonnawork0"]
What you're doing isn't meant for arrays, which are expecting sequential numeric indices (though they can technically be assigned other properties too). The type of structure you should be using is a plain object instead.
var groupedLinks = {};
for(var i = 0; i < 5; i++) {
const linkName = "59notgonnawork" + i;
groupedLinks[linkName] = new Array; // Array? plain Object? Depends on its use.
}
Why not trying to push the value in the array on each iteration.
var groupedLinks = new Array;
for(var i = 0; i < 5; i++) {
linkName = "59notgonnawork" + i;
groupedLinks.push(linkName);
}
ExtendScript Arrays are great for stocking data per indeces. If you need key/values objects, why not use… Objects ?
var groupedLinks = {};
for(var i = 0; i < 5; i++) {
linkName = "59notgonnawork" + i;
groupedLinks[linkName] = "Whatever…";
}
alert( groupedLinks["59notgonnawork0" ] ); //"Whatever…"

Javascript, adding multiple arrays to an array with a for loop

What is the best way to consolidate this code? As it is, it works perfectly, but it needs to go up to maybe 40-50 items long, so it needs to be shortened dramatically, (I assume, with a for loop).
I'm pretty much a novice when it comes to Javascript, and trying to add arrays to an array with a loop is confusing me immensely.
The "vac1.", "vac2." ...etc, variables are used later on in the code to add pointers onto a Google Maps map.
var x = count.count; // x = a value that changes (between 1 & 50)
if(x == 1){
locations = [
[vac1.vacancy_title, vac1.vacancy_latlng, vac1.vacancy_url, vac1.vacancy_location]
];
}
if(x == 2){
locations = [
[vac1.vacancy_title, vac1.vacancy_latlng, vac1.vacancy_url, vac1.vacancy_location],
[vac2.vacancy_title, vac2.vacancy_latlng, vac2.vacancy_url, vac2.vacancy_location]
];
}
if(x == 3){
locations = [
[vac1.vacancy_title, vac1.vacancy_latlng, vac1.vacancy_url, vac1.vacancy_location],
[vac2.vacancy_title, vac2.vacancy_latlng, vac2.vacancy_url, vac2.vacancy_location],
[vac3.vacancy_title, vac3.vacancy_latlng, vac3.vacancy_url, vac3.vacancy_location]
];
}
...etc etc...
I have tried using a for loop, but it doesn't work and I have no idea if I am anywhere close to figuring out how to do it correctly.
var x = count.count;
locations = [];
array = [];
for (i = 0; i < x; i++) {
array = [vac[i].vacancy_title, vac[i].vacancy_latlng, vac[i].vacancy_url, vac[i].vacancy_location];
locations.push(array);
}
Any help or advice would be greatly appreciated!
Thank you.
You need to consider them as a string:
var x = 5;
locations = [];
array = [];
for (i = 1; i <= x; i++) {
array = ['vac'+i+'.vacancy_title', 'vac'+i+'.vacancy_latlng', 'vac'+i+'.vacancy_url', 'vac'+i+'.vacancy_location'];
locations.push(array);
}
console.log(locations);
Create an array vac and use your previous code :
var x = count.count;
locations = [],
array = [],
vac = [ /* vac1, vac2, ...., vacn */ ];
for (i = 0; i < x; i++) {
array = [vac[i].vacancy_title, vac[i].vacancy_latlng, vac[i].vacancy_url, vac[i].vacancy_location];
locations.push(array);
}
You could use eval for the variable name and build an new array with another array for the wanted keys.
Basically you should reorganize yor program to use a solution without eval. An array could help. It is made for iteration.
var x = count.count,
i,
keys = ['vacancy_title', 'vacancy_latlng', 'vacancy_url', 'vacancy_location'],
locations = [];
object;
for (i = 1; i <= x; i++) {
object = eval('vac' + i);
locations.push(keys.map(function (k) { return object[k]; }));
}
Group the vac* elements in an array and then use slice to cut out as many as you want, then use map to generate the result array:
var vacs = [vac1, vac2 /*, ...*/]; // group the vacs into one single array
var x = count.count; // x is the number of vacs to generate
var locations = vacs.slice(0, x).map(function(vac) { // slice (cut out) x elements from the arrays vacs then map the cut-out array into your result array
return [vac.vacancy_title, vac.vacancy_latlng, vac.vacancy_url, vac.vacancy_location];
});
Because any global variable is a property of the global object :
var vac1 = "whatever";
console.lof(window.vac1); // => logs "whatever"
console.lof(window["vac1"]); // => accessed as an array, logs "whatever" too
You could use the global object and access it as an array to look for your vac1, vac2, vac3 variables :
var x = count.count, i;
locations = [],
array = [],
var globalObject = window; // or whatever the global object is for you
var vac; // this will be used to store your vac1, vac2, etc.
for (i = 0; i < x; i++) {
vac = globalObject["vac"+i]; // the "vac" + i variable read from the global object
if (vac !== undefined) {
array = [vac.vacancy_title, vac.vacancy_latlng, vac.vacancy_url, vac.vacancy_location];
locations.push(array);
}
}

Pass array values to another array

I have an array of input fields called '$inputFieldsArray' then I slice them to group by 3 into 'newArray' then I need new array value for each item to assign to another array cause in the end I need an array with input fields values grouped by 3. The end goal is to get an array which contains for 9 input fields ex [[i1,i2,i3],[i4,i5,i6],[i7,i8,i9]].
For some reason 'stringArray' output is nothing, first two arrays print correct results. It's probably some mistake I do regarding JS arrays.. Sorry js is not my main language, I try to learn it. Thanks.
Here is a screenshoot with chrome console:
Here is my function:
$($submitButton).click(function () {
// Get number of input fields
let $total = $("input[name^='bodyHeader']").length;
// Get input fields as objects
let $inputFieldsArray = $("input[name^='bodyHeader']");
let newArray = [];
let stringArray = [];
let j = 0;
// Group input fields by 3
for (let i = 0; i < $total - 1; i += 3) {
newArray[j] = $inputFieldsArray.slice(i, i + 3);
j++;
}
// Extract string values from newArray and pass them into stringArray
for (let k = 0; k < newArray.length - 1; k++) {
stringArray[k][0] = newArray[k][0].value;
stringArray[k][1] = newArray[k][1].value;
stringArray[k][2] = newArray[k][2].value;
}
// Print to test results
console.log($inputFieldsArray);
console.log(newArray);
console.log("String Array: " + stringArray);
... // Function logic is not complete
});
SOLUTION:
There is no way to declare dynamic length bidimensional array in js. Use this approach suggested by #Stephan :
stringArray[k] = [newArray[k][0].value, newArray[k][1].value,
newArray[k[2].value];
or this approach suggested by #Lorenzo Gangi:
var matrix = [],
cols = 3;
//init the grid matrix
for ( var i = 0; i < cols; i++ ) {
matrix[i] = [];
}
stringArray[k] is undefined because you defined stringArray as [] (Your browser probably threw an exception). Additionally newArray[k] starts at index 0.
You could write stringArray[k] = [newArray[k][0].value, newArray[k][1].value, newArray[k][2].value] instead.
Basically,
stringArray[k]
is undefined yet, therefore setting its [0] property wont work. May do:
stringArray[k] =newArray[k].map(el=>el.value);
Alltogether:
$($submitButton).click(function () {
let stringArray = $("input[name^='bodyHeader']").toArray().reduce((res,_,i,arr)=>((i%3==0 && res.push(arr.slice(i,i+3).map(e=>e.value))),res),[]);
});

Writing a recursive function which iterates through an unknown depth of nested loops

Given an array of values:
var values = new Array();
array.push(2);
array.push(3);
array.push(4);
I'd like to create an iterative function which can store every possible combination of values, for any length of array.
For example, in this case the possible values would be (1,1,1)(1,1,2)(1,1,3)(1,1,4)(1,2,1)(1,2,2)(1,2,3)(1,2,4)(2,1,1)(2,1,2)(2,1,3)(2,1,4)(2,2,1)(2,2,2)(2,2,3)(2,2,4)
I know that to do this I need to use an recursive function, which will go a level deeper and call the function again if the maximum depth has not been reached...
I know where to start is (probably, I think)
function iterativeLoop(level, depth) {
for(var i = 0; i < values.length; i++) {
if(level < depth) {
iterativeloop(level+1, depth);
}
else if (level=depth) {
}
}
}
I'm not sure how I can access the 'upper' levels once the function is called deeper though... i.e. I'm not sure how to access (1,2,4) and not just (?,?,4)
I hope that makes sense?
(Sorry I know my title isn't very good, I couldn't think how to concisely explain it)
I'm not sure how I can access the 'upper' levels once the function is called deeper though... i.e. I'm not sure how to access (1,2,4) and not just (?,?,4)
You will need to pass them on, e.g. in an array.
for(var i = 0; i < values.length; i++)
This should not be the outer iteration to perform, unless you want to construct a two-dimensional array of results in a simple nested loop (see below). Instead, you want value.length to be the depth you are recursing to. On every recursion level, you will iterate from 1 to values[level] then. And instead of passing a level, we will pass an array of the current state (the question marks from above) whose length is the level.
var values = [2,3,4];
function recurse(state) {
var level = state.length;
var depth = values.length;
if (level == depth) {
console.log.apply(console, state); // or whatever you want to do
} else {
for (var i=1; i<=values[level]; i++) {
state.push(i); // save current question mark
// notice state.length = level + 1 now
recurse(state); // enter next level
state.pop(); // delete it after we're so state doesn't grow infinitely :-)
}
}
}
recurse([]);
If you want to use your iteration over the values, you can do so by adding more and more states to a result array (growing by one value each level), which in the end will contain all possible combinations:
var values = [2,3,4];
var result = [[]]; // one empty state at level 0
for (var i=0; i<values.length; i++) {
var reslen = result.length,
val = values[i];
var mult = []; // will become the new result with a length of (reslen * val)
for (var j=0; j<reslen; j++) {
for (var k=1; k<=val; k++) {
var state = result[j].slice(); // make a copy
state.push(k);
mult.push(state);
}
}
result = mult;
}
// logging the `result` on each level will show us
// 0 - [[]]
// 1 - [[1],[2]]
// 2 - [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3]]
// 3 - [[1,1,1],[1,1,2],[1,1,3],[1,1,4],[1,2,1],[1,2,2],[1,2,3],[1,2,4],[1,3,1],[1,3,2],[1,3,3],[1,3,4],[2,1,1],[2,1,2],[2,1,3],[2,1,4],[2,2,1],[2,2,2],[2,2,3],[2,2,4],[2,3,1],[2,3,2],[2,3,3],[2,3,4]]
You can see how this is similar to #Jason's approach.
You don't need recursion since the length of the arbitrary data set is defined at the beginning at runtime:
var numbers = [2,3,4];
var result_array = [];
var num_product = 1;
var i=0, j=0, k=0; // iterators
for (i=0; i<numbers.length; i++) {
num_product *= numbers[i];
}
for (i=0; i<num_product; i++) {
result_array.push([]);
}
for (i=0; i<result_array.length; i++) {
product = 1;
for (j=0; j<numbers.length; j++) {
k = (Math.floor(i/product)%numbers[j]) + 1;
product *= numbers[j];
result_array[i][j] = k;
}
}
tested and functional for any number of array elements.
A side-by-side benchmark shows this code to be significantly faster than the recursive code - if you are able to avoid recursion (e.g. you know enough information up front to be able to define the whole problem) then it's better to do so, and the problem as currently defined allows you to do that. If you're just trying to learn about recursion, then this isn't very helpful to you :)

how to access and sort 2d array in javascript

I'm writing a script to initalize 2d array in javascript by reading txt file. Here are some portions of my code
var neighbor = {};
var temp = new Array();
neighbor[nodemap[ temparray[0]]] = temp; //nodemap[ temparray[0]] is an integer
neighbor[nodemap[temparray[0]]]. push(nodemap[temparray[1]]);
neighbor[nodemap[temparray[0]]]. push(nodemap[temparray[2]]);
.... // continue to add value
Then I want to access and sort the array, like this
for (var i = 0; i < n_count; i++);
{
for (var k = 0; k < neighbor[i].length; k++);
neighbor[k].sort(function(a,b){return a - b})
}
However, I got the error that neighbor[i] is unidentified. Could you please show me how to fix that?
Your neighbor "array" is actually an object literal. So the way you should loop over neighbor is:
for (var key in neighbor) {
var cur = neighbor[key];
cur.sort(function (a,b) {
return a - b;
});
}

Categories