On 08/31/2012 08:56 AM, Paul wrote: >> 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.
Wrap your string[string][string][string] in a user-defined type that provides "the 'in' operator" as well as opIndex and friends. I have started writing this but could not finish it yet:
import std.exception; class MyTable { string[string][string][string] elements; struct Index { string i0; string i1; string i2; } // Enables the 'auto element = myIndex in myTable' syntax // (Note: I should have called it Key, not Index.) string * opBinary(string op)(Index index) if (op == "in") { string * result = null; if (auto table0 = index.i0 in elements) { if (auto table1 = index.i1 in *table0) { if (auto element = index.i2 in *table1) { result = element; } } } return result; } // Enables 'auto value = myTable[myIndex]' ref string opIndex(Index index) { string * result = this.opBinary!"in"(index); enforce(result); return *result; } // Enables 'myTable[myIndex] = value' void opIndexAssign(string value, Index index) { auto existing = this.opIndex(index); if (existing) { existing = value; } else { // TODO: ensure that this Index exists } } // TODO: Look up oopIndexUnary and opIndexOpAssign string get(Index index, string defaultValue) { string * result = this.opBinary!"in"(index); return result ? *result : defaultValue; } } void main() {} Ali