Thread overview
Best ways to declare associative arrays
Mar 12, 2017
helxi
Mar 12, 2017
helxi
Mar 12, 2017
Nicholas Wilson
Mar 12, 2017
XavierAP
March 12, 2017
How would an experienced programmer declare an associative array of strings that has 2 keys?

My initial impression was string[string][2] my_array; which does not seem to work.

Here is a snippet of the code I am working on:


import std.string;
import std.stdio;


string[string] change(ref string[string] arg_array){
	//..
	arg_array["first"] = strip(readln());
	//..
	arg_array["second"] = strip(readln());
	//..
	return def;
}

void main(){
	string[string][2] test;
	change(string[string] test);
}
	
March 12, 2017
On Sunday, 12 March 2017 at 07:58:40 UTC, helxi wrote:
> 	return def;
I meant
        return arg_array;
March 12, 2017
On Sunday, 12 March 2017 at 07:58:40 UTC, helxi wrote:
> How would an experienced programmer declare an associative array of strings that has 2 keys?
>
> My initial impression was string[string][2] my_array; which does not seem to work.
>
> Here is a snippet of the code I am working on:
>
>
> import std.string;
> import std.stdio;
>
>
> string[string] change(ref string[string] arg_array){
> 	//..
> 	arg_array["first"] = strip(readln());
> 	//..
> 	arg_array["second"] = strip(readln());
> 	//..
> 	return def;
> }
>

You appear to be confused about the way arrays work.
string[string] foo; //declares an assoc array of strings, index by string
string[string][2] bar; // declares a static array of two string[string]
foo = { "key1" : "some data", "key2" :  "some other data" }; // initialise foo with some data
foo["blarg"] = "fxgsdzfcxf"; // insert some more data

> associative array of strings that has 2 keys?

is a regular associative array that has two entries. much like the difference between
int[] baz = [1 ,2]; // has two elements
int[][2] quux; // a static array of length 2 whose elements are of type int[]

> void main(){
> 	string[string][2] test; // remove the `[2]`
> 	change(string[string] test);
just do
        change(test);
it is invalid syntax to have a type before the variable in a function call, unless you were trying to cast it, in which use `cast(type)(expression)`
> }
> 	

If you wish to reserve capacity for the array, use `arr.reserve(N)` to allocate memory enough to hold N elements.

March 12, 2017
On Sunday, 12 March 2017 at 07:58:40 UTC, helxi wrote:
>
> string[string] change(ref string[string] arg_array){
> 	//..
> 	arg_array["first"] = strip(readln());
> 	//..
> 	arg_array["second"] = strip(readln());
> 	//..
> 	return def;
> }

Nicholas clarified why your declaration was wrong, but there are several strange things in your code that you may want to re-think. Also it looks to me that an associative array is not the most appropriate type for what you want to do.

To call a function you just pass the names of the arguments, not their types. So simply change(test), NOT change(string[string] test)

arg_array is an in-out (ref) parameter, but change() returns another value of the same type, def, not defined in your code, and which you do not use in main(). I think you may be interested only in changing arg_array, so the signature could be instead: void change(ref ...)

What you seem to want from your associative array is to associate two strings, "first" and "second" with two values (strings from the user), and only two. An associate array is more flexible than that, which is bad, you want your code to restrict you away from errors. For example if you keep using an associative array you could at the end of change(): assert(arg_array.length == 2);

I wonder if it's not enough and better for you to use a plain array. Keys "first" and "second" are not more informative than numeric indices. You may also use the advantage that an array can be hard-typed as fixed-length if this is known at compile time (and if you don't declare it with new), so it restricts your code in the perfect way:

void change(ref string[2] arg_array) {
	arg_array[0] = strip(readln());
	arg_array[1] = strip(readln());
}
void main() {
	string[2] test;
	change(test);
}

Also another disadvantage of associative arrays is that they are not ordered, so if for example in main() you read through the values in test with a foreach loop, you may get the result in any order (second first, and first second is possible). A simple array will keep order 0, 1.

If you were so bummed about using 0-1 instead of "first"-"second" you could define:

enum lineKey :size_t {
	first = 0,
	second
}
void change(ref string[2] arg_array) {
	arg_array[lineKey.first ] = strip(readln());
	arg_array[lineKey.second] = strip(readln());
}

But at least to me it looks worse. As a programmer you already know that the first index is 0 and 1 comes next.