Thread overview
Associative Array with double[][]
Jul 22, 2021
seany
Jul 22, 2021
frame
Jul 22, 2021
frame
Jul 22, 2021
bauss
July 22, 2021

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.

July 22, 2021

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.

July 22, 2021

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.

July 22, 2021

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:

double[string] diagonalLengths;

The next change would be adding the "toKey" function, something like this should work:

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:

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.