From the book a way to respond to a non-existent key in an assoc. array:
assert(aa["hello"] =3D=3D "ciao");
// Key "hello" exists, therefore ignore the second argume
assert(aa.get("hello", "salute") =3D=3D "ciao");
// Key "yo" doesn=E2=80=99t exist, return the second argument
assert(aa.get("yo", "buongiorno") =3D=3D "buongiorno");
Should this work in multidimensional arrays?
aa.get("key1" "key2" "key2", "nonexistent") =3D=3D "sometext"

D multi-key associative arrays do not exist as such, they are
associative arrays inside one another. When you write
int[string][string][double] aa;
you can use get() on aa, but only on its keys, which are of type
double, whereas its values are of type int[string][string].
I guess an effect similar to what you're asking can be obtained by
using a tuple as a key:
import std.typecons;
int[Tuple!(string,string,double)] aa;
auto p =3D aa.get(tuple("abc","def", 3.14), 0); // 0 is the default value.

From the book a way to respond to a non-existent key in an
assoc. array:
assert(aa["hello"] == "ciao");
// Key "hello" exists, therefore ignore the second argume
assert(aa.get("hello", "salute") == "ciao");
// Key "yo" doesn’t exist, return the second argument
assert(aa.get("yo", "buongiorno") == "buongiorno");
Should this work in multidimensional arrays?
aa.get("key1" "key2" "key2", "nonexistent") == "sometext"

D multi-key associative arrays do not exist as such, they are
associative arrays inside one another. When you write
int[string][string][double] aa;
you can use get() on aa, but only on its keys, which are of type
double, whereas its values are of type int[string][string].
I guess an effect similar to what you're asking can be obtained
by
using a tuple as a key:
import std.typecons;
int[Tuple!(string,string,double)] aa;
auto p = aa.get(tuple("abc","def", 3.14), 0); // 0 is the
default value.

From the book a way to respond to a non-existent key in an
assoc. array:
assert(aa["hello"] == "ciao");
// Key "hello" exists, therefore ignore the second argume
assert(aa.get("hello", "salute") == "ciao");
// Key "yo" doesn’t exist, return the second argument
assert(aa.get("yo", "buongiorno") == "buongiorno");
Should this work in multidimensional arrays?
aa.get("key1" "key2" "key2", "nonexistent") == "sometext"

D multi-key associative arrays do not exist as such, they are
associative arrays inside one another. When you write
int[string][string][double] aa;
you can use get() on aa, but only on its keys, which are of
type
double, whereas its values are of type int[string][string].
I guess an effect similar to what you're asking can be
obtained by
using a tuple as a key:
import std.typecons;
int[Tuple!(string,string,double)] aa;
auto p = aa.get(tuple("abc","def", 3.14), 0); // 0 is the
default value.

my array is of the form string[string][string][string] abc;

Maybe I'm not going about my project from the best angle?
Another problem I have is when I go to printout my array, being
associative, it is not in the order I built it. It would help
greatly if I could print it in order. Maybe I should look into
this "tuple" thing more. As well I would like to be able to
check for the existence of a particular "key" quickly without
setting up one those three-tier foreach iteration loops.

Maybe I'm not going about my project from the best angle?
Another problem I have is when I go to printout my array, being
associative, it is not in the order I built it. It would help
greatly if I could print it in order.

Hash tables (and an associative array is a hash table) are unordered, so
you're not going to get them out in the order that you put them in or anything
like that.
If you use std.container.RedBlackTree (which defaults to being a set but can
be used as a map if you adjust its comparison predicate appropriately), then
you have ordering, but it's ordered according to its predicate, not the
insertion order.
I believe that if you want a map (be it ordered or unordered) to give you
items back in the order that you inserted them, then a separate list is
required (be it integrated into the container or something you do alongside
it) where that list has the keys in the order that they were inserted into the
container.
- Jonathan M Davis

Maybe I'm not going about my project from the best angle? Another problem I
have is when I go to printout my array, being associative, it is not in the
order I built it. It would help greatly if I could print it in order.

Associative arrays reorganize themselves to allow for fast
insertion/retrieval. They do not make any promise concerning order or
printing.

Maybe I should look into this "tuple" thing more. As well I would like to
be able to check for the existence of a particular "key" quickly without
setting up one those three-tier foreach iteration loops.

A tuple is just a grouping of values together, its just a handy
predefined struct-maker in std.typecons. In your case, its equivalent
to defining
struct MyKey { string a,b,c}
string[MyKey] aa;
to fill it: aa[MyKey("abc","def","ghi")] = "my value";
It depends whether you need intermediate associative arrays
(aa["abc"], aa["abc"]["def"]) or not. It's like a 2D/3D array: do you
want access to lines / arrays or just to individual elements. In your
case, if you just want access to individual elements, using a key
grouping all your key strings under one struct might be interesting:
it means just one query in the AA.
To check for a key:
auto wanted = MyKey("abc", "def", "ghi");
if (auto p = wanted in aa) // p !is null, => the key is in the
associative array
{
// use *p
}

I believe that if you want a map (be it ordered or unordered) to give you
items back in the order that you inserted them, then a separate list is
required (be it integrated into the container or something you do alongside
it) where that list has the keys in the order that they were inserted into the
container.

Yes, that's what I wanted to propose. Group an AA and a standard,
dynamic, array. The array is just filled with the key, when you assign
a new key/value pair. To query the structure, use the AA. To print the
structure in order, iterate on this array of keys and query the AA
accordingly.
Of course, there is a downside:
* when you discard a key/value pair, your key array must be iterated
to find the now-discarded key and recreated after the key.
* when you re-assign an already defined key, you might want to put the
key in front/back of the array once more.
Pro: in order printing/iteration.
Con: slow discarding, slow re-assigning.

Yes, that's what I wanted to propose. Group an AA and a
standard,
dynamic, array. The array is just filled with the key, when you
assign
a new key/value pair. To query the structure, use the AA. To
print the
structure in order, iterate on this array of keys and query the
AA
accordingly.

So one array like- aa[MyKey("abc","def","ghi")] = "my value";
and another like- string[] da; da[99]="abc"~","~"def"~","~"ghi";
or maybe- MyKey[] da; da[99]=MyKey("abc","def","ghi");
This thread has been quite helpful already. Thanks to all.

The latter, if you group your keys, I think. You can just push the new
value at the array's end, as if it was a stack:
struct MyKey(string k1,k2,k3);
string[MyKey] aa;
MyKey[] da;
// pushing "value" with key ("abc","def","ghi"):
MyKey k = MyKey("abc","def","ghi");
aa[k] = "value";
da ~= k; // append k to da
Jonathan's advice of recording the key's index (in the array) with the
value is interesting, but then you need a special value in the array
to indicate a discarded key. Here the recent thread about Option!T
comes to mind... but I don't know what you're trying the achieve, so
let's not go into complicated stuff right now.

This thread has been quite helpful already. Thanks to all

You're welcome. Note that your need of having a structure which is
both associative and ordered is, if not unheard-of, at least somewhat
uncommon.

You're welcome. Note that your need of having a structure which
is
both associative and ordered is, if not unheard-of, at least
somewhat
uncommon.

I'm parsing program blocks from a proprietary HW/SW system. They
provide the data in the form of:
Somegroupname/Someblockname
someparam=value
anotherparam=value
...
otherparam=value
end
Somegroupname/Somediffblockname
someparam=value
anotherparam=value
...
otherparam=value
end
Someothergroupname/Someotherblockname
p1=value
p2=value
...
px=value
end
The data is in an ascii text file.
I need to be able to search it by group/block/parameter.
I need to be able to maintain group/block order.
There are ~hundred diff block types where the params and order of
params are known...though I would rather not create all of these
structures or lists ahead of time.
My greatest need at this point is to compare two files block by
block. The blocks may be in diff orders between the files but
the params of each block type would always be the same in the
same order.
So compare groups, blocks within groups, and the values of each
param for matching group/block names.

The data is in an ascii text file.
I need to be able to search it by group/block/parameter.
I need to be able to maintain group/block order.
There are ~hundred diff block types where the params and order of params are
known...though I would rather not create all of these structures or lists
ahead of time.
My greatest need at this point is to compare two files block by block. The
blocks may be in diff orders between the files but the params of each block
type would always be the same in the same order.
So compare groups, blocks within groups, and the values of each param for
matching group/block names.

I see. In that case, your original idea of having a three-tier
associative array (AA in AA in AA) is better than my tuple-key
suggestion, since you want to look into all three levels. Does the
provider ensure that no two groups have the same name and no two
blocks in a group have the same name?
If the blocks are in a different order, you don't care about order,
right? Then use an AA. As params of each block always have the same
order, you can use a dynamic array.
So:
struct Param
{
string name, value;
}
struct Block
{
string name;
Param[] params;
}
struct Group
{
string name;
Block[string] blocks;
}
alias Group[string] InputFile;
InputFile file1, file2;
Maybe someone here will have a better idea?

You're welcome. Note that your need of having a structure which is
both associative and ordered is, if not unheard-of, at least somewhat
uncommon.

I'm parsing program blocks from a proprietary HW/SW system. They provide
the data in the form of:
Somegroupname/Someblockname
someparam=value
anotherparam=value
...
otherparam=value
end
Somegroupname/Somediffblockname
someparam=value
anotherparam=value
...
otherparam=value
end
Someothergroupname/Someotherblockname
p1=value
p2=value
...
px=value
end
The data is in an ascii text file.
I need to be able to search it by group/block/parameter.
I need to be able to maintain group/block order.
There are ~hundred diff block types where the params and order of params
are known...though I would rather not create all of these structures or
lists ahead of time.
My greatest need at this point is to compare two files block by block.
The blocks may be in diff orders between the files but the params of
each block type would always be the same in the same order.
So compare groups, blocks within groups, and the values of each param
for matching group/block names.

I believe that if you want a map (be it ordered or unordered) to give you
items back in the order that you inserted them, then a separate list is
required (be it integrated into the container or something you do
alongside
it) where that list has the keys in the order that they were inserted into
the container.

Yes, that's what I wanted to propose. Group an AA and a standard,
dynamic, array. The array is just filled with the key, when you assign
a new key/value pair. To query the structure, use the AA. To print the
structure in order, iterate on this array of keys and query the AA
accordingly.
Of course, there is a downside:
* when you discard a key/value pair, your key array must be iterated
to find the now-discarded key and recreated after the key.
* when you re-assign an already defined key, you might want to put the
key in front/back of the array once more.
Pro: in order printing/iteration.
Con: slow discarding, slow re-assigning.

Yeah, though I expect that there are ways to make it a less of a problem. For
instance, you could make it so that the hash table's value was really a tuple
of the value and the index into the array or vector holding the keys in
insertion order (or use a second hash table to hold the indices). Then when
you remove an item, you use the index from the value in the table and set that
element in the array to a value indicating that it's empty (so that it's
skipped when iterating over it). Then removing items is as fast as inserting
them. The problem that that causes of course is that the list of inserted keys
keeps growing, but as long as it doesn't make rehashing too expensive, you
could adjust the array (and the indices in the hash table) when you rehash
(and possibly after a certain number of removals as well in case the table
gets items removed often enough that rehashing isn't ever necessary). That may
or may not be the best solution, but I expect that it's problem that's already
been explored and probably has some good existing solutions somewhere.
In general though, you just don't care about insertion order into a hash
table, which takes care of the whole problem.
- Jonathan M Davis