Sharikov Vladislav
Sharikov Vladislav

Reputation: 7269

Associative array of arrays on java script (dynamic)

UPDATE — I will try to explain it again

I need to do next:

  1. Create graph creator
  2. Use some alghorithms to search shortest path from A vertex to B vertex.

Firstly, I need to draw graph on web-page. I use Graph Dracula Library (don't pay much attention to it, my answer is not about it, I just said it, so question will be full). Secondy, I am working with array of arrays.

When I add 1 vertex to page, I will have to add 1 row into array of arrays and 1 column to each old row of array of arrays. When I add edge between two vertexes I will have to UPDATE array of arrays. When I delete vertex, I will have to delete row, connected with this vertex, and delete column, connected to this vertex, in each row in array of arrays.

EXAMPLES:

1 Page is blank, array of arrays is:

[ ]

2 Add 3 vertexes:

Page is: 3 vertex

Matrix (array of arrays) is:

[
    [0, 0, 0],
    [0, 0, 0],
    [0, 0, 0]
]

3 Delete 2nd vertex:

Page is: delete 2nd vertex

Matrix is:

[
    [0, 0],
    [0, 0]
]

Pay attention, that vertex on page are 1 and 3, but in matrix there are only 2 rows/columns WHICH ARE NOT CONNECTED to page. So connection losted. Now 3 vertex on page is 2nd column in each element/row in matrix.

4 For example, adding 1 more vertex.

In page:

error

Matrix is:

[
    [0, 0, 0],
    [0, 0, 0],
    [0, 0, 0]
]

We have 1, 3 and 4 vertexes on page, but only 3 rows/columns in matrix. 2nd row/column belongs to 3 vertex on page, 3rd row/column of matrix belongs to 4 vertex on page.

5 etc etc etc. There are no connection between matrix and page, so my programm works not correcly.

Problem

I can get access to vertex on page only by its name. Like 1 or 3. So I must:

Update 50% of dracula's code (it is impossible for me)
or
Create and work with matrix with another methods. I think assoc matrix will solve my problem, but I don't know how to build/work with assoc matrix. Thats my question. How to do this? Or, if assoc array is not a good idea, give me example how to work with objects, please.

I need something like this:

// adding 1, 2, 3 vertexes
deleteVertex('3'); // this will delete both `3` vertex on page and in matrix
addVertex(); // this will add 4 (!) vertex on page and 4 vertex to matrix

Help me please!

P.S.: You can get see example of how I work with matrix on OLD QUESTION part.

OLD QUESTION

I have next problem. I need to create dynamic array of arrays. I am building graph creator (programm to draw graphs).

I am working with .

How I work with array of arrays. On first call vertexCount is 0.

// 1. Upgrade old rows and add 1 new column to each
for (var i = 0; i < vertexCount; i++)
{   
    weightArray[i][vertexCount] = 0;
}

// 2. Add new row
weightArray[vertexCount] = [];

// 3. Fill this row with zeros
for (var i = 0; i <= vertexCount; i++)
{
    weightArray[vertexCount][i] = 0;
}

All working fine. But, I get access to vertex by it's name. Example: I created 5 vertexes. Names are: 1, 2, 3, 4, 5. I deleted 3rd vertex. Names are: 1, 2, 4, 5 now. I added 1 vertex. Names are: 1, 2, 4, 5, 6 now. Now if I try to delete 4rd vertex, 5 vertex will be deleted, not 4 (because 5th vertex has index 4). If I try to delete 6th vertex, I will get error, because there are no 6th vertex in matrix.

It's sad, but I am working with framework, so I can't rewrite how to add vertexes. How can I change my code (look 'how I work with array of arrays code') so I can get access to vertexes by name in matrix? I need assoc array, but I don't know how to do it. Help please.

P.S.: delete code:

for (var i = 0; i < vertexCount; i++)
{
    delete weightArray[i][target-1];
}
delete weightArray[target-1];

vertexCount = vertexCount - 1;

When I understand how to create/fill assoc array, I will have to rewrite part where I delete vertexes

Upvotes: 0

Views: 111

Answers (2)

Sharikov Vladislav
Sharikov Vladislav

Reputation: 7269

This worked:

var weightArray = {};

// 1. Upgrade old rows and add 1 new column to each
for (row in weightArray)
{   
    weightArray[row][totalVertex+1] = 0;
}

// 2. Add new row
weightArray[totalVertex+1] = {};

// 3. Fill this row with zeros
for (row in weightArray)
{
    weightArray[totalVertex+1][row] = 0;
}

All become fine, when I started to work with objects.

Upvotes: 0

Patrick Evans
Patrick Evans

Reputation: 42736

when you delete an array element, the index does not actually get deleted. So your decreasing the vertexCount is wrong as it will contain the wrong length as the length of the array will still be the same after a delete. You can avoid this by using splice

for(var i=0; i<weightArray.length; i++){
   weightArray[i].splice(1,target-1);
}
weightArray.splice(1,target-1);

Also note that you do not need to keep track of the array length (ie vertexCount) you can just get the length of the array right from the array object.

EDIT

Then just do a delete and nothing else, no need for the loop or anything else.

delete matrix[vertexNumber]

As said earlier when you delete an element from an array the index doesnt actually get deleted

So using your example matrix with 3 vertices would look like:

[
   [ 0, 0, 0],  <-- vertex 0
   [ 0, 0, 0],  <-- vertex 1
   [ 0, 0, 0]   <-- vertex 2
]

and when you delete from array, say vertex 1, it will look like this

[
   [ 0, 0, 0],  <-- vertex 0
   undefined,   <-- old vertext 1, now equals undefined
   [ 0, 0 ,0]   <-- vertext 2
]

So your indexes are still the same, try the code below in like in the console to view

var matrix = [];
matrix[0] = [0,0,0];
matrix[1] = [0,0,0];
matrix[2] = [0,0,0];

console.log(matrix);
//[
//   [ 0, 0, 0],  <-- vertex 0
//   [ 0, 0, 0],  <-- vertex 1
//   [ 0, 0, 0]   <-- vertex 2
//]
console.log(matrix.length);
//3

Now if we delete vertex 1

delete matrix[1];
console.log(matrix);
//[
//   [ 0, 0, 0],  <-- vertex 0
//   undefined,   <-- vertex 1
//   [ 0, 0, 0]   <-- vertex 2
//]
console.log(matrix.length);
//3

Then add vertex 3

matrix[3] = [0,0,0];
console.log(matrix);
//[
//   [ 0, 0, 0],  <-- vertex 0
//   undefined,   <-- vertex 1
//   [ 0, 0, 0],  <-- vertex 2
//   [ 0, 0, 0]   <-- vertex 3
//]
console.log(matrix.length);
//4

Now delete vertex 3 and add vertex 4

delete matrix[3];
matrix[4] = [0,0,0];
console.log(matrix);
//[
//   [ 0, 0, 0],  <-- vertex 0
//   undefined,   <-- vertex 1
//   [ 0, 0, 0],   <-- vertex 2
//   undefined,   <-- vertex 3
//   [ 0, 0, 0]   <-- vertex 4
//]
console.log(matrix.length);
//5

as you can see the elements do not reposition themselves. So all you have to do is use

delete matrix[vertexNumber]

and that's it as the elements keep their index. So even when say you delete vertex 1, vertex 2 will still be at 2

Extra Edit

To keep the matrix square, this is where you would use vertexCount. Keep track by decreasing it or increasing it as you add/remove vertex

Then when you need to add a row loop through and add the extra column if needed

for(var i=0; i<matrix.length; i++){
   //if its one of the undefined indexes just continue
   if(!matrix[i]) continue;
   if(matrix[i].length < vertexCount){
      var numExtraCols = vertexCount-matrix[i].length;
      //Just a way to create an array with X number of slots
      var extraCols = Array.apply(null,Array(extraCols)).map(Boolean).map(Number);
      matrix[i].concat(extraCols);
   }
}

And when you delete a vertex

for(var i=0; i<matrix.length; i++){
   //if its one of the undefined indexes just continue
   if(!matrix[i]) continue;
   if(matrix[i].length > vertexCount){
      var numExtraCols = vertexCount - matrix[i].length;
      //remove X number of columns starting from the end.
      matrix[i].splice(numExtraCols,matrix[i].length-1);
   }
}

Note though since your array is keeping all the indexes its still going to have to iterate over it, which could have performance hit. Do not know if this would be a bigger performance hit then using an object or not. You will have to do tests.

to do with object, its mostly the same except you start matrix off as a object and not an array, and the looping is a bit different, but the size does change as when you delete a objects property the key is deleted with it

var matrix = {};
matrix[0] = [0,0,0];
matrix[1] = [0,0,0];
matrix[2] = [0,0,0];

to loop over it

var keys = Object.keys(matrix);
for(var i=0; i<keys.length; i++){
   //use 
   matrix[ keys[i] ]
   //in place of
   matrix[i]
}

and deleting is the same

delete matrix[3]

Also since object does not have a native length you will have to do something like

var numVertexes = Object.keys(matrix).length;

Upvotes: 3

Related Questions