Thread overview
Accessing contents of associative arrays in an optimal way
Jul 09, 2016
phant0m
Jul 09, 2016
Ali Çehreli
Jul 09, 2016
ag0aep6g
Jul 09, 2016
phant0m
July 09, 2016
Suppose I have AA of structures:

struct Foo {
    int value;
    string name;
}

Foo[int] records;

As far as I know, AA implemented as a hashtable. So, will there be two searches performed (one search for each line)?
records[3].value = 10;
records[3].name = "name";

How can I access elements of this AA by a "reference"? In C++ I can use reference to an element of the map:
Foo& foo = records.find(3).second;
foo.value = 10;
foo.name = "name";

I found that in D I can use a "with" keyword to achieve the same effect:
with(values[0]) {
    value = 10;
    name = "name";
}

Is this the only optimal way?

July 09, 2016
On 07/09/2016 01:32 PM, phant0m wrote:
> Suppose I have AA of structures:
>
> struct Foo {
>      int value;
>      string name;
> }
>
> Foo[int] records;
>
> As far as I know, AA implemented as a hashtable. So, will there be two
> searches performed (one search for each line)?
> records[3].value = 10;
> records[3].name = "name";

Yes, two searches. Although it is slower, it's still O(1). :)

> How can I access elements of this AA by a "reference"?

The 'in' operator returns a pointer to the element:

import std.stdio;

struct Foo {
     int value;
     string name;
}

void main() {
    Foo[int] records;
    records[3] = Foo(42, "hello");

    if (auto record = 3 in records) {
        record.value = 10;
        record.name = "name";
    }

    writeln(records);
}

Ali

July 09, 2016
On 07/09/2016 10:32 PM, phant0m wrote:
> As far as I know, AA implemented as a hashtable. So, will there be two
> searches performed (one search for each line)?
> records[3].value = 10;
> records[3].name = "name";

Yup. A good optimizer may be able to eliminate one, but conceptually there are two lookups.

> How can I access elements of this AA by a "reference"? In C++ I can use
> reference to an element of the map:
> Foo& foo = records.find(3).second;
> foo.value = 10;
> foo.name = "name";

You can take the address of `records[3]`:

----
Foo* foo = &records[3];
foo.value = 10;
foo.name = "name";
----

If `records[3]` may be not set, you can use `3 in records` to get a pointer to the value or null if the key isn't set:

----
Foo* foo = 3 in records;
if (foo is null) {records[0] = Foo.init; foo = 3 in records;}
foo.value = 10;
foo.name = "name";
----
July 09, 2016
Thank you!