www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Associative Array with double[][]

reply seany <seany uni-bonn.de> writes:
I have a perimeter of a shape, given by a `double [][]` . I want 
to keep the lengths of various diagonals in another associative 
array.

So,

     /// define some associative array to keep track of diagonals 
here..

     auto perimeter = new double[][] (0,0);

     /// --- fill up perimeter here ---

     for(int i = 0; i < perimeter.length; i++) {
       for ( int j = 0; j < perimeter.length; j++) {

       //// fill up the associative array here

       }
     }


So, I would like to do this:

     double[ double[][]] diagonalLengths;
     auto perimeter = new double[][] (0,0);

     /// --- fill up perimeter here ---

     for(int i = 0; i < perimeter.length; i++) {
       for ( int j = 0; j < perimeter.length; j++) {

       auto diag_point_i = perimeter[i];
       auto diag_point_j = perimeter[j];

       diagonalLengths [ [diag_point_i, diag_point_j]] = 
calculate_length (i,j);

       }
     }


This is necessary, as further processing will change the indices 
of the points in the perimeter. I can't therefore use ` 
diagonalLengths [ [i,j]] = calculate_length (i,j);`

However, trying to do this is resulting to :

`test.d(29): Error: associative arrays can only be assigned 
values with immutable keys, not `double[][]`

What are my options now?  Do I have to convert the array which i 
plan to use as a key to a struct and define opEquals and toHash?

Are there automatic hashing mechanisms for this?

If there are multiple possibilities, what is the fastest in terms 
of memory? Thank you.
Jul 21 2021
next sibling parent reply frame <frame86 live.com> writes:
On Thursday, 22 July 2021 at 03:13:14 UTC, seany wrote:

 If there are multiple possibilities, what is the fastest in 
 terms of memory? Thank you.
I believe the fastest way (as seen from your loop) would be using pointer arithmetric and using void* keys for diagonalLengths and an index function that is able to pick the void* key/address from the given double coordinates. You may also consider using a binary tree data structure instead of AA.
Jul 21 2021
parent frame <frame86 live.com> writes:
On Thursday, 22 July 2021 at 04:46:13 UTC, frame wrote:

Of course a double* makes more sense than a void* type for the AA 
here.
Jul 21 2021
prev sibling parent bauss <jj_1337 live.dk> writes:
On Thursday, 22 July 2021 at 03:13:14 UTC, seany wrote:
 I have a perimeter of a shape, given by a `double [][]` . I 
 want to keep the lengths of various diagonals in another 
 associative array.

 So,

     /// define some associative array to keep track of 
 diagonals here..

     auto perimeter = new double[][] (0,0);

     /// --- fill up perimeter here ---

     for(int i = 0; i < perimeter.length; i++) {
       for ( int j = 0; j < perimeter.length; j++) {

       //// fill up the associative array here

       }
     }


 So, I would like to do this:

     double[ double[][]] diagonalLengths;
     auto perimeter = new double[][] (0,0);

     /// --- fill up perimeter here ---

     for(int i = 0; i < perimeter.length; i++) {
       for ( int j = 0; j < perimeter.length; j++) {

       auto diag_point_i = perimeter[i];
       auto diag_point_j = perimeter[j];

       diagonalLengths [ [diag_point_i, diag_point_j]] = 
 calculate_length (i,j);

       }
     }


 This is necessary, as further processing will change the 
 indices of the points in the perimeter. I can't therefore use ` 
 diagonalLengths [ [i,j]] = calculate_length (i,j);`

 However, trying to do this is resulting to :

 `test.d(29): Error: associative arrays can only be assigned 
 values with immutable keys, not `double[][]`

 What are my options now?  Do I have to convert the array which 
 i plan to use as a key to a struct and define opEquals and 
 toHash?

 Are there automatic hashing mechanisms for this?

 If there are multiple possibilities, what is the fastest in 
 terms of memory? Thank you.
A possible but not that beautiful solution would be using string keys. And then using UFC to make a "toKey" function that takes your double[][] as parameter. To do this the first change would be your associative array has to be changed to: ```d double[string] diagonalLengths; ``` The next change would be adding the "toKey" function, something like this should work: ```d string asKey(double[][] d) { import std.algorithm : map; import std.array : array, join; import std.conv : to; return d.map!(e => e.map!(i => i.to!string).join("_")).array.join(":"); } ``` The last change would be accessing the associative array you simply do it like this: ```d diagonalLengths [ [diag_point_i, diag_point_j].asKey] ``` As you can see the only change in your logic is just adding the .asKey function call. It's of course not gonna be fast or anything but it's functional.
Jul 22 2021