Associative array/Creation: Difference between revisions

From Rosetta Code
Content added Content deleted
(Add Seed7 example)
Line 2,044: Line 2,044:
(define my-hash (alist->hash-table my-alist))
(define my-hash (alist->hash-table my-alist))
</lang>
</lang>

=={{header|Seed7}}==
Seed7 uses the type [http://seed7.sourceforge.net/manual/types.htm#hash hash] to support associative arrays.

<lang seed7>$ include "seed7_05.s7i";

# Define hash type
const type: myHashType is hash [string] integer;

# Define hash table
var myHashType: aHash is myHashType.value;

const proc: main is func
local
var string: stri is "";
var integer: number is 0;
begin
# Add elements
aHash @:= ["foo"] 42;
aHash @:= ["bar"] 100;

# Check presence of an element
if "foo" in aHash then

# Access an element
writeln(aHash["foo"]);
end if;

# Change an element
aHash @:= ["foo"] 7;

# Remove an element
excl(aHash, "foo");

# Loop over the hash values
for number range aHash do
writeln(number);
end for;

# Loop over the hash keys
for key stri range aHash do
writeln(stri);
end for;

# Loop over hash keys and values
for number key stri range aHash do
writeln("key: " <& stri <& ", value: " <& number);
end for;
end func;</lang>


=={{header|Slate}}==
=={{header|Slate}}==

Revision as of 09:54, 9 July 2011

Task
Associative array/Creation
You are encouraged to solve this task according to the task description, using any language you may know.

In this task, the goal is to create an associative array (also known as a dictionary, map, or hash).

ActionScript

Because ActionScript does not have associative arrays in the normal sense, Object objects are used instead and keys are simply properties on those objects. <lang actionscript>var map:Object = {key1: "value1", key2: "value2"}; trace(map['key1']); // outputs "value1"

// Dot notation can also be used trace(map.key2); // outputs "value2"

// More keys and values can then be added map['key3'] = "value3"; trace(map['key3']); // outputs "value3"</lang> Note: The Object only supports String keys. To use an object as a key, try the flash.utils.Dictionary class.

Ada

Works with: GNAT version GPL 2007

<lang ada>with Ada.Containers.Ordered_Maps; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Text_IO;

procedure Associative_Array is

  -- Instantiate the generic package Ada.Containers.Ordered_Maps
  package Associative_Int is new Ada.Containers.Ordered_Maps(Unbounded_String, Integer);
  use Associative_Int;
 
  Color_Map : Map;
  Color_Cursor : Cursor;
  Success : Boolean;
  Value : Integer;

begin

  -- Add values to the ordered map
  Color_Map.Insert(To_Unbounded_String("Red"), 10, Color_Cursor, Success);
  Color_Map.Insert(To_Unbounded_String("Blue"), 20, Color_Cursor, Success);
  Color_Map.Insert(To_Unbounded_String("Yellow"), 5, Color_Cursor, Success);
  -- retrieve values from the ordered map and print the value and key
  -- to the screen
  Value := Color_Map.Element(To_Unbounded_String("Red"));
  Ada.Text_Io.Put_Line("Red:" & Integer'Image(Value));
  Value := Color_Map.Element(To_Unbounded_String("Blue"));
  Ada.Text_IO.Put_Line("Blue:" & Integer'Image(Value));
  Value := Color_Map.Element(To_Unbounded_String("Yellow"));
  Ada.Text_IO.Put_Line("Yellow:" & Integer'Image(Value));

end Associative_Array;</lang>

Aikido

Aikido provides a native map for associative arrays. You can create them using a map literal and you can insert and remove items on the fly. <lang aikido> var names = {} // empty map names["foo"] = "bar" names[3] = 4

// initialized map var names2 = {"foo": bar, 3:4}

// lookup map var name = names["foo"] if (typeof(name) == "none") {

   println ("not found")

} else {

   println (name)

}

// remove from map delete names["foo"]


</lang>

ALGOL 68

Translation of: C++
Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny

<lang algol68>main:(

 MODE COLOR = BITS;
 FORMAT color repr = $"16r"16r6d$;
 # This is an associative array which maps strings to ints #
 MODE ITEM = STRUCT(STRING key, COLOR value);
 REF[]ITEM color map items := LOC[0]ITEM;
 PROC color map find = (STRING color)REF COLOR:(
   REF COLOR out;
  1. linear search! #
   FOR index FROM LWB key OF color map items TO UPB key OF color map items DO
     IF color = key OF color map items[index] THEN 
       out := value OF color map items[index]; GO TO found
     FI
   OD;
     NIL EXIT
   found:
     out
 );
 PROC color map = (STRING color)REF COLOR:(
   REF COLOR out = color map find(color);
   IF out :=: REF COLOR(NIL) THEN # extend color map array #
     HEAP[UPB key OF color map items + 1]ITEM color map append;
     color map append[:UPB key OF color map items] := color map items;
     color map items := color map append;
     value OF (color map items[UPB value OF color map items] := (color, 16r000000)) # black #
   ELSE
     out
   FI
 );
 
 # First, populate it with some values #
 color map("red") := 16rff0000;
 color map("green") := 16r00ff00;
 color map("blue") := 16r0000ff;
 color map("my favourite color") := 16r00ffff;
 
 # then, get some values out #
 COLOR color := color map("green"); # color gets 16r00ff00 # 
 color := color map("black"); # accessing unassigned values assigns them to 16r0 #
 
 # get some value out without accidentally inserting new ones #
 REF COLOR value = color map find("green");
 IF value :=: REF COLOR(NIL) THEN
   put(stand error, ("color not found!", new line))
 ELSE
   printf(($"green: "f(color repr)l$, value))
 FI;
 
 # Now I changed my mind about my favourite color, so change it #
 color map("my favourite color") := 16r337733;
 
 # print out all defined colors #
 FOR index FROM LWB color map items TO UPB color map items DO
   ITEM item = color map items[index];
   putf(stand error, ($"color map("""g""") = "f(color repr)l$, item))
 OD;
 FORMAT fmt;
 FORMAT comma sep = $"("n(UPB color map items-1)(f(fmt)", ")f(fmt)")"$;
 fmt := $""""g""""$;
 printf(($g$,"keys: ", comma sep, key OF color map items, $l$));
 fmt := color repr;
 printf(($g$,"values: ", comma sep, value OF color map items, $l$))

)</lang> Output:

green: 16r00ff00
color map("red") = 16rff0000
color map("green") = 16r00ff00
color map("blue") = 16r0000ff
color map("my favourite color") = 16r337733
color map("black") = 16r000000
keys: ("red", "green", "blue", "my favourite color", "black")
values: (16rff0000, 16r00ff00, 16r0000ff, 16r337733, 16r000000)

APL

Works with: Dyalog APL

<lang apl>⍝ Create a namespace ("hash")

     X←⎕NS ⍬
     
     ⍝ Assign some names
     X.this←'that'
     X.foo←88
     
     ⍝  Access the names
     X.this

that

     ⍝  Or do it the array way
     X.(foo this)

88 that

     ⍝  Namespaces are first class objects
     sales ← ⎕NS ⍬
     sales.(prices quantities) ← (100 98.4 103.4 110.16) (10  12 8  10)
     sales.(revenue ← prices +.× quantities)
     sales.revenue

4109.6</lang>

AWK

Arrays in AWK are indeed associative arrays. <lang awk>BEGIN {

 a["red"] = 0xff0000
 a["green"] = 0x00ff00
 a["blue"] = 0x0000ff
 for (i in a) {
   printf "%8s %06x\n", i, a[i] 
 }
 # deleting a key/value
 delete a["red"]
 for (i in a) {
   print i
 }
 # check if a key exists
 print ( "red" in a )   # print 0
 print ( "blue" in a )  # print 1

}</lang>

AutoHotkey

AutoHotkey does not have typical arrays. However, variable names can be concatenated, simulating associative arrays. Just without the syntactic sugar of '[]'. <lang AutoHotkey>arrayX1 = first arrayX2 = second arrayX3 = foo arrayX4 = bar Loop, 4

 Msgbox % arrayX%A_Index%</lang>

Batch File

This is cheating, I'm sure of it.

<lang dos>::assocarrays.cmd @echo off setlocal ENABLEDELAYEDEXPANSION set array.dog=1 set array.cat=2 set array.wolf=3 set array.cow=4 for %%i in (dog cat wolf cow) do call :showit array.%%i !array.%%i! set c=-27 call :mkarray sicko flu 5 measles 6 mumps 7 bromodrosis 8 for %%i in (flu measles mumps bromodrosis) do call :showit "sicko^&%%i" !sicko^&%%i! endlocal goto :eof

mkarray

set %1^&%2=%3 shift /2 shift /2 if "%2" neq "" goto :mkarray goto :eof

showit

echo %1 = %2 goto :eof </lang>

Output:

array.dog = 1
array.cat = 2
array.wolf = 3
array.cow = 4
"sicko&flu" = 5
"sicko&measles" = 6
"sicko&mumps" = 7
"sicko&bromodrosis" = 8

Brat

<lang brat>h = [:] #Empty hash

h[:a] = 1 #Assign value h[:b] = [1 2 3] #Assign another value

h2 = [a: 1, b: [1 2 3], 10 : "ten"] #Initialized hash

h2[:b][2] #Returns 3</lang>

C

There are no associative arrays in the C language. Some libraries provide hash tables, red-black trees, or other data structures that can become associative arrays. Some of these libraries are awful. There are too many easy ways to get a compiler error or a segfault.

Judy

Example using Judy.

Library: Judy

<lang c>#include <stdio.h>

  1. include <Judy.h>

int main() {

 Pvoid_t assarray = (Pvoid_t) NULL;
 PWord_t value;
 int retval;
 /* populating */
 JSLI(value, assarray, "red");
 *value = 0xff0000;
 JSLI(value, assarray, "green");
 *value = 0x00ff00;
 JSLI(value, assarray, "blue");
 *value = 0x0000ff;
 /* retrieving existent */
 JSLG(value, assarray, "blue");
 printf("blue is #%06lx\n", (unsigned long)*value);
 /* unknown key */
 JSLG(value, assarray, "nonexistingkey");
 if ( value == NULL ) { fprintf(stderr, "key 'nonexistingkey' does not exists\n"); }
 /* deleting */
 JSLD(retval, assarray, "red");
 JSLG(value, assarray, "red");
 if ( value == NULL ) { fprintf(stderr, "key red does not exist anymore\n"); }
 JudySLFreeArray(&assarray, PJE0);
 return 0;

}</lang>

POSIX hcreate()

POSIX defines hcreate(), hdestroy() and hsearch() to manage a hash table. If you have a Unix system or clone, then your libc probably has these functions, so there is no extra library to install.

  • You can only have one hash table, in the entire program!
    • With GNU libc, you can call hcreate_r() to have more than one hash table.
  • There is no way to delete an entry from the table!
  • There is no way to iterate all keys in the table!
  • Every key must be a NUL-terminated string.
  • Every value is a void *, needs a cast to the correct type.
  • The table might become full, and refuse to accept more entries. If you use hcreate(50) then the table might hold at most 50 entries.
  • hdestroy() is almost impossible to use. Many programs keep the table and never call hdestroy().
    • With BSD libc, hdestroy() will call free() with each key in the table.
    • Else the program leaks memory, because there is no way to iterate the keys to free them.

The Linux manual page hcreate(3) has a short example.

The next example shows how to use hdestroy(), how to use intptr_t as a value, how to use double as a key, and how to pretend to delete an entry from the table! POSIX hash table is awful, and the code is too long, but the program does run.

Library: POSIX

<lang c>#include <inttypes.h> /* PRIxPTR */

  1. include <search.h> /* hcreate(), hsearch(), hdestroy() */
  2. include <stdint.h> /* intptr_t */
  3. include <stdio.h> /* perror(), printf(), puts(), snprintf() */
  4. include <stdlib.h> /* calloc(), exit(), free() */
  5. include <string.h> /* strdup() */

void fail(char *message) { perror(message); exit(1); }


/*

* color_example:
*   Maps color strings to integer values, like "red" => 0xff0000.
*
* Because the values (ENTRY data) are pointers, I use casts to and from
* intptr_t to store integers instead of pointers.
*/

void color_example(void) { ENTRY e, *ep; int i;

puts("color_example:");

/* Create an empty table. */ if (hcreate(50) == 0) fail("hcreate");

/* Add keys => values to table. */ { char *keys[] = { "red", "green", "blue" }; intptr_t values[] = { 0xff0000, 0x00ff00, 0x0000ff };

for (i = 0; i < 3; i++) { /* Need strdup() when using ENTER. */ if ((e.key = strdup(keys[i])) == NULL) fail("strdup"); e.data = (void *)values[i];

/* Insert e into table. */ if (hsearch(e, ENTER) == NULL) fail("hsearch"); } }

/* Check if keys exist. */ { char *keys[] = { "blue", "green", "orange", "red" };

for (i = 0; i < 4; i++) { /* Not using ENTER, so no strdup(). */ e.key = keys[i]; ep = hsearch(e, FIND); if (ep) { printf("\t'%s' has value %06" PRIxPTR "\n", ep->key, (intptr_t)ep->data); } else printf("\t'%s' is not in table\n", e.key); } }

/* * Destroy table. On my machine, hdestroy() will free() all the * keys in the table. This is why I had to strdup() my keys. */ hdestroy(); }


/*

* number_example:
*   Maps numbers to strings or numbers, like 2 => 2.71828 or 4 => "four".
*
* First I need a VALUE that can either be a string or a number.
*/

typedef struct value { int v_type;

  1. define T_NUM 0x1 /* use v_num */
  2. define T_STR 0x2 /* use v_str */
  3. define T_DEL 0x4 /* pretend to delete from table */

union { double u_num; char *u_str; } v_union;

  1. define v_num v_union.u_num
  2. define v_str v_union.u_str

struct value *next; /* link all VALUEs in a list */ } VALUE;

void number_example(void) { ENTRY e, *ep; VALUE *all = NULL, *vp; int i, s; char buf[16];

puts("number_example:");

if (hcreate(50) == 0) fail("hcreate");

/* Add numeric values. */ { double keys[] = { 2, 3, 4, 5.6 }; double values[] = { 2.71828, 3.14159, 4.47214, 7.8 };

for (i = 0; i < 4; i++) { /* Must convert keys to strings. */ snprintf(buf, sizeof buf, "%.6g", keys[i]); if ((e.key = strdup(buf)) == NULL) fail("strdup");

/* Allocate a new VALUE. */ if ((vp = calloc(1, sizeof vp[0])) == NULL) fail("calloc"); vp->v_type = T_NUM; vp->v_num = values[i]; e.data = vp;

/* Remember to free it. */ vp->next = all; all = vp;

if (hsearch(e, ENTER) == NULL) fail("hsearch"); } }

/* * Add string values. * * For this example, all of my values will be static string * constants. This removes the need to free(vp->v_str) * when I replace or delete a value. */ { double keys[] = { 4, 8, 10 }; char *values[] = { "four", "eight", "ten" };

for (i = 0; i < 3; i++) { /* Must convert keys to strings. */ snprintf(buf, sizeof buf, "%.6g", keys[i]);

/* * This shows how to add or replace a value * in the table (so I can change an entry * from 4 => 4.47214 to 4 => "four"). */ e.key = buf; ep = hsearch(e, FIND); if (ep) { /* Already have key. Change value. */ vp = (VALUE *)ep->data; vp->v_type = T_STR; vp->v_str = values[i]; } else { /* Need to add key. */ if ((e.key = strdup(buf)) == NULL) fail("strdup");

if ((vp = calloc(1, sizeof vp[0])) == NULL) fail("calloc"); vp->v_type = T_STR; vp->v_str = values[i]; e.data = vp;

/* Remember to free it. */ vp->next = all; all = vp;

if (hsearch(e, ENTER) == NULL) fail("hsearch"); } } }

/* Delete key 8. */ snprintf(buf, sizeof buf, "%.6g", (double)8); e.key = buf; ep = hsearch(e, FIND); if (ep) { vp = (VALUE *)ep->data; vp->v_type = T_DEL; }

/* Check if keys exist. */ { double keys[] = { 2, 3, 4, 5.6, 7, 8, 10 };

for (i = 0; i < 7; i++) { snprintf(buf, sizeof buf, "%.6g", keys[i]); e.key = buf; ep = hsearch(e, FIND);

if (ep == NULL || (vp = (VALUE *)ep->data)->v_type & T_DEL) { printf("\t%s is not in the table\n", buf); } else if (vp->v_type & T_NUM) { printf("\t%s has value %g\n", buf, vp->v_num); } else if (vp->v_type & T_STR) { printf("\t%s has value '%s'\n", buf, vp->v_str); } else { printf("\t%s has invalid value\n", buf); } } }

/* Destroy table and keys. */ hdestroy();

/* Free all values. */ while (all != NULL) { vp = all->next; free(all); all = vp; } }

int main() { color_example(); number_example(); return 0; }</lang>

Output:

color_example:
        'blue' has value 0000ff
        'green' has value 00ff00
        'orange' is not in table
        'red' has value ff0000
number_example:
        2 has value 2.71828
        3 has value 3.14159
        4 has value 'four'
        5.6 has value 7.8
        7 is not in the table
        8 is not in the table
        10 has value 'ten'

BSD dbopen()

BSD provides dbopen() in <db.h>. This is Berkeley DB 1.85. Because dbopen() often puts a database on disk, one easily forgets that dbopen(NULL, ...) can put a small database in memory. When the type is DB_BTREE or DB_HASH, then the database is an associative array.

  • Warning: some GNU/Linux systems have a dbopen(3) manual page without a real dbopen() function. See Debian bug #337581.

The next example translates the previous example to dbopen(). Every key and value is a *void, needs a cast to the correct type. Because BSD also has <err.h>, I remove fail() and use err().

Library: BSD libc
Works with: OpenBSD version 4.8

<lang c>#include <sys/types.h>

  1. include <err.h> /* err() */
  2. include <fcntl.h>
  3. include <limits.h>
  4. include <stdio.h> /* printf(), puts() */
  5. include <string.h> /* memset() */
  6. include <db.h> /* dbopen() */

/*

* color_example:
*   Maps color strings to integer values, like "red" => 0xff0000.
*/

void color_example(void) { DB *db; DBT key, value; int i, r;

puts("color_example:");

/* Create an empty table. */ db = dbopen(NULL, O_RDWR, 0777, DB_HASH, NULL); if (db == NULL) err(1, "dbopen");

/* Add keys => values to table. */ { char *keys[] = { "red", "green", "blue" }; int values[] = { 0xff0000, 0x00ff00, 0x0000ff };

for (i = 0; i < 3; i++) { /* key.size must count the '\0' byte */ key.data = keys[i]; key.size = strlen(keys[i]) + 1; value.data = &values[i]; value.size = sizeof values[i];

/* * Insert key, value into table. DB will * allocate its own storage for key, value. */ if (db->put(db, &key, &value, 0) < 0) err(1, "db->put"); } }

/* Check if keys exist. */ { char *keys[] = { "blue", "green", "orange", "red" };

for (i = 0; i < 4; i++) { key.data = (void *)keys[i]; key.size = strlen(keys[i]) + 1;

r = db->get(db, &key, &value, 0); if (r < 0) err(1, "db->get"); else if (r > 0) { printf("\t'%s' is not in table\n", (char *)key.data); } else { printf("\t'%s' has value %06x\n", (char *)key.data, *(int *)value.data); } } }

/* Destroy table. */ db->close(db); }


/*

* number_example:
*   Maps numbers to strings or numbers, like 2 => 2.71828 or 4 => "four".
*
* First I need a VALUE that can either be a string or a number.
*/

typedef struct value { int v_type;

  1. define T_NUM 0x1 /* use v_num */
  2. define T_STR 0x2 /* use v_str */

union { double u_num; char *u_str; } v_union;

  1. define v_num v_union.u_num
  2. define v_str v_union.u_str

} VALUE;

void number_example(void) { DB *db; DBT key, value; VALUE v, *vp; double d; int i, r;

puts("number_example:");

db = dbopen(NULL, O_RDWR, 0777, DB_HASH, NULL); if (db == NULL) err(1, "dbopen");

/* Add numeric values. */ { double keys[] = { 2, 3, 4, 5.6 }; double values[] = { 2.71828, 3.14159, 4.47214, 7.8 };

for (i = 0; i < 4; i++) { memset(&v, 0, sizeof v); v.v_type = T_NUM; v.v_num = values[i];

key.data = &keys[i]; key.size = sizeof keys[i]; value.data = &v; value.size = sizeof v;

if (db->put(db, &key, &value, 0) < 0) err(1, "db->put"); } }

/* * Add string values. * * For this example, all of my values will be static string * constants. This removes the need to free(vp->v_str) * when I replace or delete a value. */ { double keys[] = { 4, 8, 10 }; char *values[] = { "four", "eight", "ten" };

for (i = 0; i < 3; i++) { memset(&v, 0, sizeof v); v.v_type = T_STR; v.v_str = values[i];

key.data = &keys[i]; key.size = sizeof keys[i]; value.data = &v; value.size = sizeof v;

/* * db->put can replace an entry (so I can change * it from 4 => 4.47214 to 4 => "four"). * * I am storing the strings outside the DB. * To put them inside the DB, I would need to * remove the v.v_str pointer and append each * string data to value.data. */ if (db->put(db, &key, &value, 0) < 0) err(1, "db->put"); } }

/* Delete key 8. */ d = 8; key.data = &d; key.size = sizeof d; r = db->del(db, &key, 0); if (r < 0) err(1, "db->del");

/* Iterate all keys. */ r = db->seq(db, &key, &value, R_FIRST); if (r < 0) err(1, "db->seq"); else if (r > 0) puts("\tno keys!"); else { printf("\tall keys: %g", *(double *)key.data); while ((r = db->seq(db, &key, &value, R_NEXT)) == 0) printf(", %g", *(double *)key.data); if (r < 0) err(1, "db->seq"); puts(""); }

/* Check if keys exist. */ { double keys[] = { 2, 3, 4, 5.6, 7, 8, 10 };

for (i = 0; i < 7; i++) { key.data = &keys[i]; key.size = sizeof keys[i];

r = db->get(db, &key, &value, 0); if (r < 0) err(1, "db->get"); else if (r > 0) { printf("\t%g is not in the table\n", keys[i]); continue; }

vp = (VALUE *)value.data; if (vp->v_type & T_NUM) { printf("\t%g has value %g\n", keys[i], vp->v_num); } else if (vp->v_type & T_STR) { printf("\t%g has value '%s'\n", keys[i], vp->v_str); } else { printf("\t%g has invalid value\n", keys[i]); } } }

db->close(db); }

int main() { color_example(); number_example(); return 0; }</lang>

Output:

color_example:
        'blue' has value 0000ff
        'green' has value 00ff00
        'orange' is not in table
        'red' has value ff0000
number_example:
        all keys: 2, 3, 5.6, 4, 10
        2 has value 2.71828
        3 has value 3.14159
        4 has value 'four'
        5.6 has value 7.8
        7 is not in the table
        8 is not in the table
        10 has value 'ten'

BSD sys/tree.h

Library: BSD libc
Works with: OpenBSD version 4.8

<lang c>#include <sys/tree.h>

  1. include <err.h> /* err() */
  2. include <stdio.h> /* printf(), puts() */
  3. include <stdlib.h> /* calloc(), free() */
  4. include <string.h> /* strcmp() */

/*

* color_example:
*   Maps color strings to integer values, like "red" => 0xff0000.
*
* I will use a red-black tree of type 'struct ctree', which contains
* nodes of type 'struct cnode'.
*/

struct cnode { RB_ENTRY(cnode) entry; char *key; int value; };

int cnodecmp(struct cnode *a, struct cnode *b) { return strcmp(a->key, b->key); }

RB_HEAD(ctree, cnode); RB_GENERATE(ctree, cnode, entry, cnodecmp)

void color_example(void) { struct ctree head = RB_INITIALIZER(&head); /* an empty tree */ struct cnode n, *np, *op; int i;

puts("color_example:");

/* Add keys => values to tree. */ { char *keys[] = { "red", "green", "blue" }; int values[] = { 0xff0000, 0x00ff00, 0x0000ff };

for (i = 0; i < 3; i++) { if ((np = calloc(1, sizeof np[0])) == NULL) err(1, "calloc"); np->key = keys[i]; np->value = values[i]; RB_INSERT(ctree, &head, np); } }

/* Check if keys exist. */ { char *keys[] = { "blue", "green", "orange", "red" };

for (i = 0; i < 4; i++) { n.key = keys[i]; np = RB_FIND(ctree, &head, &n);

if (np) { printf("\t'%s' has value %06x\n", np->key, np->value); } else { printf("\t'%s' is not in tree\n", n.key); } } }

/* Free tree. */ for (np = RB_MIN(ctree, &head); np != NULL; np = op) { op = RB_NEXT(ctree, &head, np); RB_REMOVE(ctree, &head, np); free(np); } }


/*

* number_example:
*   Maps numbers to strings or numbers, like 2 => 2.71828 or 4 => "four".
*
* This node has a value that can either be a string or a number.
*/

struct dnode { RB_ENTRY(dnode) entry; double key; int v_type;

  1. define T_NUM 0x1 /* use v_num */
  2. define T_STR 0x2 /* use v_str */

union { double u_num; char *u_str; } v_union;

  1. define v_num v_union.u_num
  2. define v_str v_union.u_str

};

int dnodecmp(struct dnode *a, struct dnode *b) { double aa = a->key; double bb = b->key; return (aa < bb) ? -1 : (aa > bb); }

RB_HEAD(dtree, dnode); RB_GENERATE(dtree, dnode, entry, dnodecmp)

void number_example(void) { struct dtree head = RB_INITIALIZER(&head); struct dnode n, *np, *op; int i;

puts("number_example:");

/* Add numeric values. */ { double keys[] = { 2, 3, 4, 5.6 }; double values[] = { 2.71828, 3.14159, 4.47214, 7.8 };

for (i = 0; i < 4; i++) { if ((np = calloc(1, sizeof np[0])) == NULL) err(1, "calloc"); np->key = keys[i]; np->v_type = T_NUM; np->v_num = values[i]; RB_INSERT(dtree, &head, np); } }

/* * Add string values. * * For this example, all of my values will be static string * constants. This removes the need to free(np->v_str) * when I replace or delete a value. */ { double keys[] = { 4, 8, 10 }; char *values[] = { "four", "eight", "ten" };

for (i = 0; i < 3; i++) { /* * This shows how to add or replace a value * in the tree (so I can change an entry * from 4 => 4.47214 to 4 => "four"). */ n.key = keys[i]; if (np = RB_FIND(dtree, &head, &n)) { np->v_type = T_STR; np->v_str = values[i]; } else if (np = calloc(1, sizeof np[0])) { np->key = keys[i]; np->v_type = T_STR; np->v_str = values[i]; RB_INSERT(dtree, &head, np); } else err(1, "calloc"); } }

/* Delete key 8. */ n.key = 8; if (np = RB_FIND(dtree, &head, &n)) RB_REMOVE(dtree, &head, np);

/* Iterate all keys. */ i = 1; RB_FOREACH(np, dtree, &head) { if (i) { printf("\tall keys: %g", np->key); i = 0; } else printf(", %g", np->key); } if (i) puts("\tno keys!"); else puts("");

/* Check if keys exist. */ { double keys[] = { 2, 3, 4, 5.6, 7, 8, 10 };

for (i = 0; i < 7; i++) { n.key = keys[i]; np = RB_FIND(dtree, &head, &n);

if (np == NULL) { printf("\t%g is not in the tree\n", keys[i]); } else if (np->v_type & T_NUM) { printf("\t%g has value %g\n", keys[i], np->v_num); } else if (np->v_type & T_STR) { printf("\t%g has value '%s'\n", keys[i], np->v_str); } else { printf("\t%g has invalid value\n", keys[i]); } } }

/* Free tree. */ for (np = RB_MIN(dtree, &head); np != NULL; np = op) { op = RB_NEXT(dtree, &head, np); RB_REMOVE(dtree, &head, np); free(np); } }

int main() { color_example(); number_example(); return 0; }</lang>

Output:

color_example:
        'blue' has value 0000ff
        'green' has value 00ff00
        'orange' is not in tree
        'red' has value ff0000
number_example:
        all keys: 2, 3, 4, 5.6, 10
        2 has value 2.71828
        3 has value 3.14159
        4 has value 'four'
        5.6 has value 7.8
        7 is not in the tree
        8 is not in the tree
        10 has value 'ten'

C++

The C++ standard defines std::map as a means of creating an association between a key of one arbitrary type and a value of another arbitrary type. This requires the inclusion of the standard header map.

<lang cpp>#include <map></lang>

Creation

To create a simple map whose key is of type A and whose value is of type B, one would define the variable like so: <lang cpp>std::map<A, B> exampleMap</lang>

If one wanted to us a key type of int and a value of double, you would define it like so:

<lang cpp>std::map<int, double> exampleMap</lang>

Insertion

Once we've created our map, we've got a couple different ways to insert the value. Let's use an example key of 7, and an exable value of 3.14.

Operator[]

The first method is using the [] operator. <lang cpp>exampleMap[7] = 3.14</lang>

Of course, you can use a variable (or any rvalue of the correct type) for the key or value parameters: <lang cpp>int myKey = 7; double myValue = 3.14; exampleMap[myKey] = myValue;</lang>

insert()

The second approach is a little more complicated. We have to use the pair<> template: <lang cpp>exampleMap.insert(std::pair<int, double>(7,3.14));</lang> or by using make_pair to avoid repeating key/value types: <lang cpp>exampleMap.insert(std::make_pair(7,3.14));</lang>

Lookup

As with insertion, there are a couple ways we can retrieve the value.

operator[]

We use it as an rvalue, supplying the correct key: <lang cpp>myValue = exampleMap[myKey]</lang> If the value doesn't already exist, a default-constructed object of the value's type will be inserted using the key you specified, and that default value will be returned.

find()

Alternatively, you can look up a value by using find(), storing its return value in an iterator, and comparing the iterator against the map's end() sentinal value: <lang cpp>double myValue = 0.0; std::map<int, double>::iterator myIterator = exampleMap.find(myKey); if(exampleMap.end() != myIterator) {

 // Return the value for that key.
 myValue = myIterator->second;

}</lang>

The need for the ->second code is because our iterator points to a pair<>(), and our value is the second member of that pair.

This code assigns a 0 to myValue if the map contained a value.

Example

This simple program creates a map, assigns a value to that map, retrieves a value from that map, and prints the value to STDOUT. <lang cpp>#include <map>

  1. include <iostreams>

int main() {

 // Create the map.
 std::map<int, double> exampleMap;
 // Choose our key
 int myKey = 7;
 // Choose our value
 double myValue = 3.14;
 // Assign a value to the map with the specified key.
 exampleMap[myKey] = myValue;
 // Retrieve the value
 double myRetrievedValue = exampleMap[myKey];
 // Display our retrieved value.
 std::cout << myRetrievedValue << std::endl;
 // main() must return 0 on success.
 return 0;

}</lang>

C#

Platform: .NET 1.x <lang csharp>System.Collections.HashTable map = new System.Collections.HashTable(); map["key1"] = "foo";</lang>

Platform: .NET 2.0 <lang csharp>Dictionary<string, string> map = new Dictionary<string,string>(); map[ "key1" ] = "foo";</lang>

Works with: C# version 3.0+

<lang csharp>var map = new Dictionary<string, string> Template:"key1", "foo";</lang>

Clojure

<lang lisp>{:key "value"

:key2 "value2"
:key3 "value3"}</lang>

ColdFusion

<lang cfm><cfset myHash = structNew()> <cfset myHash.key1 = "foo"> <cfset myHash["key2"] = "bar"> <cfset myHash.put("key3","java-style")></lang>

In ColdFusion, a map is literally a java.util.HashMap, thus the above 3rd method is possible.

Common Lisp

<lang lisp>;; default :test is #'eql, which is suitable for numbers only,

or for implementation identity for other types!
Use #'equalp if you want case-insensitive keying on strings.

(setf my-hash (make-hash-table :test #'equal)) (setf (gethash "H2O" my-hash) "Water") (setf (gethash "HCl" my-hash) "Hydrochloric Acid") (setf (gethash "CO" my-hash) "Carbon Monoxide")

That was actually a hash table, an associative array or
alist is written like this

(defparameter *legs* '((cow . 4) (flamingo . 2) (centipede . 100)))

you can use assoc to do lookups and cons new elements onto it to make it longer.</lang>

D

<lang d>void main() {

   auto hash = ["foo":42, "bar":100];
   assert("foo" in hash);

}</lang>

Dao

<lang dao>m = { => } # empty, future inserted keys will be ordered h = { : } # empty, future inserted keys will not be ordered

m = { 'foo' => 42, 'bar' => 100 } # with ordered keys h = { 'foo' : 42, 'bar' : 100 } # with unordered keys</lang>

E

<lang e>[].asMap() # immutable, empty ["one" => 1, "two" => 2] # immutable, 2 mappings [].asMap().diverge() # mutable, empty ["one" => 2].diverge(String, float64) # mutable, initial contents,

                                       #   typed (coerces to float)</lang>

F#

.NET 3.5 Generic Dictionary (mutable) <lang fsharp> let dic = System.Collections.Generic.Dictionary<string,string>() ;; dic.Add("key","val") ; dic.["key"] <- "new val" ; </lang> Functional dictionary (immutable) <lang fsharp> let d = [("key","val");("other key","other val")] |> Map.ofList let newd = d.Add("new key","new val")

let takeVal (d:Map<string,string>) =

   match d.TryFind("key") with
       | Some(v) -> printfn "%s" v
       | None -> printfn "not found"  

</lang>

Factor

Associative mappings follow the associative protocol. See the docs. Here's an example using a hashtable that can be run in the listener : <lang factor>H{ { "one" 1 } { "two" 2 } } { [ "one" swap at . ]

 [ 2 swap value-at . ]
 [ "three" swap at . ]
 [ [ 3 "three" ] dip set-at ]
 [ "three" swap at . ] } cleave</lang>

Fantom

Associative arrays are called 'maps' in Fantom:

<lang fantom> class Main {

 public static Void main ()
 {
   // create a map which maps Ints to Strs, with given key-value pairs
   Int:Str map := [1:"alpha", 2:"beta", 3:"gamma"]
   // create an empty map
   Map map2 := [:]
   // now add some numbers mapped to their doubles
   10.times |Int i| 
   { 
     map2[i] = 2*i 
   }
 }

} </lang>

Forth

Works with: GNU Forth version 0.6.2

The Forth dictionary is normally only used for function and symbol definitions, but you can also define separate wordlists for holding functions or data. There is no special syntax in the language for this, but you can define your own. All of Forth's defining words are available for adding things to the wordlist, but CREATE is most generic.

<lang forth>: get ( key len table -- data ) \ 0 if not present

 search-wordlist if
   >body @
 else 0 then ;
put ( data key len table -- )
 >r 2dup r@ search-wordlist if
   r> drop nip nip
   >body !
 else
   r> get-current >r set-current      \ switch definition word lists
   nextname create ,
   r> set-current
 then ;
wordlist constant bar

5 s" alpha" bar put 9 s" beta" bar put 2 s" gamma" bar put s" alpha" bar get . \ 5 8 s" Alpha" bar put \ Forth dictionaries are normally case-insensitive s" alpha" bar get . \ 8</lang> This is not necessarily a good option in all Forths, as the dictionary may be implemented as a simple linked list (normally not a problem because the dictionary is only used for compiling and interactive interpretation). GNU Forth and many other hosted Forths use hash tables for the dictionary, so this is a fine choice. If you need case-sensitive keys, GNU Forth has table and table-find, replacing wordlist and search-wordlist, respectively.

(The use of nextname ( str len -- ) is a GNU Forth extension to create; there is no means in the ANS standard to use a string on the stack to create a dictionary entry.)

Hashtable for mapping strings to integer <lang forth>include ffl/hct.fs

\ Create a hash table 'table' in the dictionary with a starting size of 10

10 hct-create htable

\ Insert entries

5 s" foo" htable hct-insert

10 s" bar" htable hct-insert 15 s" baz" htable hct-insert

\ Get entry from the table

s" bar" htable hct-get [IF]

 .( Value:) . cr

[ELSE]

 .( Entry not present.) cr

[THEN]</lang>

Go

Go's maps can only have a key type that is boolean, numeric, string, pointer, function, interface, map, or channel; you cannot use a key type of array, slice, or struct. <lang go>// declare a nil map variable, for maps from string to int var x map[string] int

// make an empty map x = make(map[string] int)

// make an empty map with an optional initial capacity x = make(map[string] int, 42)

// set a value x["foo"] = 3

// make a map with a literal x = map[string] int {

 "foo": 2, "bar": 42, "baz": -1,

}</lang>

Groovy

Create an empty map and add values <lang groovy>map = [:] map[7] = 7 map['foo'] = 'foovalue' map.put('bar', 'barvalue') map.moo = 'moovalue'

assert 7 == map[7] assert 'foovalue' == map.foo assert 'barvalue' == map['bar'] assert 'moovalue' == map.get('moo')</lang>

Create a pre-populated map and verify values <lang groovy>map = [7:7, foo:'foovalue', bar:'barvalue', moo:'moovalue']

assert 7 == map[7] assert 'foovalue' == map.foo assert 'barvalue' == map['bar'] assert 'moovalue' == map.get('moo')</lang>

Haskell

Works with: GHC

<lang haskell>import Data.Map

dict = fromList [("key1","val1"), ("key2","val2")]

ans = Data.Map.lookup "key2" dict -- evaluates to "val2" </lang>

Icon and Unicon

Icon and Unicon associative arrays are called tables. Any value may be used as a key including complex structures. Tables can have default values and they have no inherent size limitation growing from empty to whatever size is needed.

<lang icon>procedure main()

  local t
  t := table() 
  t["foo"] := "bar"
  write(t["foo"])

end</lang>

Inform 7

The Inform 7 equivalent of an associative array is a relation between values.

Static relation

<lang inform7>Hash Bar is a room.

Connection relates various texts to one number. The verb to be connected to implies the connection relation.

"foo" is connected to 12. "bar" is connected to 34. "baz" is connected to 56.

When play begins: [change values] now "bleck" is connected to 78; [check values] if "foo" is connected to 12, say "good."; if "bar" is not connected to 56, say "good."; [retrieve values] let V be the number that "baz" relates to by the connection relation; say "'baz' => [V]."; end the story.</lang>

Dynamic relation

<lang inform7>Hash Bar is a room.

When play begins: let R be a various-to-one relation of texts to numbers; [initialize the relation] now R relates "foo" to 12; now R relates "bar" to 34; now R relates "baz" to 56; [check values] if R relates "foo" to 12, say "good."; if R does not relate "bar" to 56, say "good."; [retrieve values] let V be the number that "baz" relates to by R; say "'baz' => [V]."; end the story.</lang>

Ioke

<lang ioke>{a: "a", b: "b"}</lang>

J

<lang J> coclass 'assocArray'

 create=: 3 :'erase COCREATOR'
 get=: ".
 set=:4 :'(x)=:y'</lang>

Example use:

   example=: conew~'assocArray'
   'foo' set__example 1 2 3
1 2 3
   'bar' set__example 4 5 6
4 5 6
   get__example 'foo'
1 2 3
   foo__example
1 2 3
   bletch__example=: 7 8 9
   get__example 'bletch'
7 8 9

Java

Works with: Java version 1.5+

Defining the Map: <lang java5>Map<String, Integer> map = new HashMap<String, Integer>(); map.put("foo", 5); map.put("bar", 10); map.put("baz", 15); map.put("foo", 6);</lang> "Putting" a value for a key that already exists ("map.put("foo", 6)" in this example) will replace and return the old value for the key.

Initializing a Map as a class member: <lang java5>public static Map<String, Integer> map = new HashMap<String, Integer>(){{

  put("foo", 5);
  put("bar", 10);
  put("baz", 15);
  put("foo", 6);

}};</lang> Retrieving a value: <lang java5>map.get("foo"); // => 5 map.get("invalid"); // => null</lang> Note that it is possible to put null as a value, so null being returned by get is not sufficient for determining that the key is not in the Map. There is a containsKey method for that.

Iterate over keys: <lang java5>for (String key: map.keySet())

  System.out.println(key);</lang>

Iterate over values: <lang java5>for (int value: map.values())

  System.out.println(value);</lang>

Iterate over key, value pairs: <lang java5>for (Map.Entry<String, Integer> entry: map.entrySet())

  System.out.println(entry.getKey() + " => " + entry.getValue());</lang>

JavaScript

In Javascript we make an associative array from an empty object, otherwise if we make it from an array we'll get all the Array object's method and properties when we iterate over it. Note that this associative array uses strings as its key, but automagically casts other types to strings if used as indices: <lang javascript>var assoc = {}; assoc['foo'] = 'bar'; assoc['another-key'] = 3; assoc.thirdKey = 'we can also do this!'; assoc[2] = 'the index here is the string "2"'; assoc[null] = 'this also works';

for (key in assoc) {

 if (assoc.hasOwnProperty(key)) {
   alert('key:"' + key + '", value:"' + assoc[key] + '"');
 }

}</lang>

We use hasOwnProperty to ensure that the key is not inherited from some other object

The above associative array can also be constructed using Javascript's object literal syntax <lang javascript>var assoc = {

 foo: 'bar',
 'another-key': 3 //the key can either be enclosed by quotes or not

};</lang>

Notice the quotes on some names. When quoting the names you avoid potential collisions with reserved JavaScript key words. http://www.quackit.com/javascript/javascript_reserved_words.cfm

We can also check whether a key exists in an object or not: <lang javascript>'foo' in assoc // true</lang>

UCB Logo has "property lists" which associate names with values. They have their own namespace. <lang logo>pprop "animals "cat 5 pprop "animals "dog 4 pprop "animals "mouse 11 print gprop "animals "cat  ; 5 remprop "animals "dog show plist "animals  ; [mouse 11 cat 5]</lang>

Lua

Lua tables are Hashes <lang lua>hash = {} hash[ "key-1" ] = "val1" hash[ "key-2" ] = 1 hash[ "key-3" ] = {}</lang> Returns nil on unknown key.

NetRexx

<lang NetRexx>/* NetRexx */

options replace format comments java crossref savelog symbols

key0 = '0' key1 = 'key0'

hash = '.' -- Initialize the associative array 'hash' to '.' hash[key1] = 'value0' -- Set a specific key/value pair

say '<hash key="'key0'" value="'hash[key0]'" />' -- Display a value for a key that wasn't set say '<hash key="'key1'" value="'hash[key1]'" />' -- Display a value for a key that was set </lang>

Output:

<hash key="0" value="." />
<hash key="key0" value="value0" />

Objective-C

Works with: Cocoa

and

Works with: GNUstep

You can use a NSDictionary to create an immutable hash. A dictionary can contain only objects; if you want store non objects like integer, you have to box it in NSNumber. <lang objc>NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:

   @"Joe Doe", @"name",
   [NSNumber numberWithUnsignedInt:42], @"age",
   [NSNull null], @"extra",
   nil];</lang>

To create a mutable dictionary, use NSMutableDictionary: <lang objc>NSMutableDictionary *dict = [NSMutableDictionary dictionary]; [dict setObject:@"Joe Doe" forKey:@"name"]; [dict setObject:[NSNumber numberWithInt:42] forKey:@"age"];</lang>

You can access value with objectForKey:. If a key does not exists, nil is returned. <lang objc>NSString *name = [dict objectForKey:@"name"]; unsigned age = [dict objectForKey:@"age"] unsignedIntValue]; id missing = [dict objectForKey:@"missing"];</lang>

Objeck

Object parameters must be implicitly casted to the types expected by the method that's called.

Associative map

<lang objeck>

  1. create map

map := StringMap->New();

  1. insert

map->Insert("two", IntHolder->New(2)->As(Base)); map->Insert("thirteen", IntHolder->New(13)->As(Base)); map->Insert("five", IntHolder->New(5)->As(Base)); map->Insert("seven", IntHolder->New(7)->As(Base));

  1. find

map->Find("thirteen")->As(IntHolder)->GetValue()->PrintLine(); map->Find("seven")->As(IntHolder)->GetValue()->PrintLine(); </lang>

Hash table

<lang objeck>

  1. create map

map := StringHash->New();

  1. insert

map->Insert("two", IntHolder->New(2)->As(Base)); map->Insert("thirteen", IntHolder->New(13)->As(Base)); map->Insert("five", IntHolder->New(5)->As(Base)); map->Insert("seven", IntHolder->New(7)->As(Base));

  1. find

map->Find("thirteen")->As(IntHolder)->GetValue()->PrintLine(); map->Find("seven")->As(IntHolder)->GetValue()->PrintLine(); </lang>

OCaml

Hash table

A simple idiom to create a hash table mapping strings to integers: <lang ocaml>let hash = Hashtbl.create 0;; List.iter (fun (key, value) -> Hashtbl.add hash key value)

 ["foo", 5; "bar", 10; "baz", 15];;</lang>

To retrieve a value: <lang ocaml>let bar = Hashtbl.find hash "bar";; (* bar = 10 *)</lang> To retrieve a value, returning a default if the key is not found: <lang ocaml>let quux = try Hashtbl.find hash "quux" with Not_found -> some_value;;</lang>

Binary tree

A simple idiom to create a persistent binary tree mapping strings to integers: <lang ocaml>module String = struct

  type t = string
  let compare = Pervasives.compare

end module StringMap = Map.Make(String);;

let map =

 List.fold_left
   (fun map (key, value) -> StringMap.add key value map)
   StringMap.empty
   ["foo", 5; "bar", 10; "baz", 15]
</lang>

To retrieve a value: <lang ocaml>let bar = StringMap.find "bar" map;; (* bar = 10 *)</lang> To retrieve a value, returning a default if the key is not found: <lang ocaml>let quux = try StringMap.find "quux" map with Not_found -> some_value;;</lang>

Oz

A mutable map is called a 'dictionary' in Oz: <lang oz>declare

 Dict = {Dictionary.new}

in

 Dict.foo := 5
 Dict.bar := 10
 Dict.baz := 15
 Dict.foo := 20
 {Inspect Dict}</lang>

'Records' can be consideres immutable maps: <lang oz>declare

 Rec = name(foo:5 bar:10 baz:20)

in

 {Inspect Rec}</lang>

Perl

Hash

Definition: <lang perl># using => key does not need to be quoted unless it contains special chars my %hash = (

 key1 => 'val1',
 'key-2' => 2,
 three => -238.83,
 4 => 'val3',

);

  1. using , both key and value need to be quoted if containing something non-numeric in nature

my %hash = (

 'key1', 'val1',
 'key-2', 2,
 'three', -238.83,
 4, 'val3',

);</lang>

Use: <lang perl>print $hash{key1};

$hash{key1} = 'val1';

@hash{'key1', 'three'} = ('val1', -238.83);</lang>

HashRef

Definition: <lang perl>my $hashref = {

key1 => 'val1',
 'key-2' => 2,
 three => -238.83,
 4 => 'val3',

}</lang>

Use: <lang perl>print $hash->{key1};

$hash->{key1} = 'val1';

@hash->{'key1', 'three'} = ('val1', -238.83);</lang>

Perl 6

Works with: Rakudo version #22 "Thousand Oaks"

The fatarrow, =>, is no longer just a quoting comma; it now constructs a Pair object. But you can still define a hash with an ordinary list of even length.

<lang perl6>my %h1 = key1 => 'val1', 'key-2' => 2, three => -238.83, 4 => 'val3'; my %h2 = 'key1', 'val1', 'key-2', 2, 'three', -238.83, 4, 'val3';</lang>

Hash elements and hash slices now use the same sigil as the whole hash. This is construed as a feature. Curly braces no longer auto-quote, but Perl 6's qw (shortcut < ... >) now auto-subscripts.

<lang perl6>say %h1{'key1'}; say %h1<key1>; %h1<key1> = 'val1'; %h1<key1 three> = 'val1', -238.83;</lang>

Special syntax is no longer necessary to access a hash stored in a scalar.

<lang perl6>my $h = {key1 => 'val1', 'key-2' => 2, three => -238.83, 4 => 'val3'}; say $h<key1>;</lang>

PHP

<lang php>$array = array(); $array['foo'] = 'bar'; $array['bar'] = 'foo';

echo($array['foo']); // bar echo($array['moo']); // Undefined index

//alternative (inline) way $array2 = array('fruit' => 'apple',

               'price' => 12.96,
               'colour' => 'green');</lang>

Iterate over key/value

<lang php>foreach($array as $key => $value) {

  echo "Key: $key Value: $value";

}</lang>

PicoLisp

Here we use symbol properties. Other possiblities could be index trees or association lists.

<lang PicoLisp>(put 'A 'foo 5) (put 'A 'bar 10) (put 'A 'baz 15) (put 'A 'foo 20)

(get 'A 'bar)

-> 10

(get 'A 'foo)

-> 20

(show 'A)

A NIL

  foo 20
  bar 10
  baz 15</lang>

Pop11

<lang pop11>;;; Create expandable hash table of initial size 50 and with default

value 0 (default value is returned when the item is absent).

vars ht = newmapping([], 50, 0, true);

Set value corresponding to string 'foo'

12 -> ht('foo');

print it

ht('foo') =>

Set value corresponding to vector {1 2 3}

17 -> ht({1 2 3});

print it

ht({1 2 3}) =>

Set value corresponding to number 42 to vector {0 1}

{0 1} -> ht(42);

print it

ht(42) =>

Iterate over keys printing keys and values.
appproperty(ht,
   procedure (key, value);
     printf(value, '%p\t');
     printf(key, '%p\n');
    endprocedure);</lang>

PostScript

<lang postscript>

<</a 100 /b 200 /c 300>>
dup /a get =

</lang>

PowerShell

Am empty hash table can be created with <lang powershell>$hashtable = @{}</lang> A hash table can be initialized with key/value pairs: <lang powershell>$hashtable = @{

   "key1" = "value 1"
   "key2" = 5

}</lang> Individual values can be assigned or replaced by either using a property-style access method or indexing into the table with the given key: <lang powershell>$hashtable.foo = "bar" $hashtable['bar'] = 42 $hashtable."a b" = 3.14 # keys can contain spaces, property-style access needs quotation marks, then $hashtable[5] = 8 # keys don't need to be strings</lang> Similarly, values can be retrieved using either syntax: <lang powershell>$hashtable.key1 # value 1 $hashtable['key2'] # 5</lang>

A shortcut to CREATE an OBJECT with empty fields: <lang powershell>$addressObj= "" | Select-Object nameStr,street1Str,street2Str,cityStr,stateStr,zipStr $addressObj.nameStr = [string]"FirstName LastName" $addressObj.street1Str= [string]"1 Main Street" $addressObj.cityStr= [string]"Washington DC" $addressObj.stateStr= [string]"DC" $addressObj.zipStr= [string]"20009" </lang>

Prolog

We use the facts table for this purpose. <lang prolog> mymap(key1,value1). mymap(key2,value2).

?- mymap(key1,V).

  V = value1

</lang>

PureBasic

Hashes are a built-in type called Map in Purebasic.

<lang python>NewMap dict.s() dict("country") = "Germany" Debug dict("country")</lang>

Python

Hashes are a built-in type called dictionaries (or mappings) in Python.

<lang python>hash = dict() # 'dict' is the dictionary type. hash = dict(red="FF0000", green="00FF00", blue="0000FF") hash = { 'key1':1, 'key2':2, } value = hash[key]</lang>

Numerous methods exist for the mapping type http://docs.python.org/lib/typesmapping.html

<lang python># empty dictionary d = {} d['spam'] = 1 d['eggs'] = 2

  1. dictionaries with two keys

d1 = {'spam': 1, 'eggs': 2} d2 = dict(spam=1, eggs=2)

  1. dictionaries from tuple list

d1 = dict([('spam', 1), ('eggs', 2)]) d2 = dict(zip(['spam', 'eggs'], [1, 2]))

  1. iterating over keys

for key in d:

 print key, d[key]
  1. iterating over (key, value) pairs

for key, value in d.iteritems():

 print key, value</lang>

Note: Python dictionary keys can be of any arbitrary "hashable" type. The following contains several distinct key value pairs:

<lang python>myDict = { '1': 'a string', 1: 'an integer', 1.0: 'a floating point number', (1,): 'a tuple' }</lang>

(Some other languages such as awk and Perl evaluate all keys such that numerically or lexically equivalent expressions become identical entries in the hash or associative array).

User defined classes which implement the __hash__() special method can also be used as dictionary keys. It's the responsibility of the programmer to ensure the properties of the resultant hash value. The instance object's unique ID (accessible via the id() built-in function) is commonly used for this purpose.

R

The R object which is the most similar to an associative array is called list; a list can take labels (tags) <lang R>a <- list(a=1, b=2, c=3.14, d="xyz")</lang>

If tags are omitted, numerical tags in increasing order (from 1) are assigned.

<lang R>print(a$a) # [1] 1 print(a$d) # [1] "xyz"</lang>

But we can always access the element of a list with its numeric index, or take directly the value:

<lang R>print(a[4])</lang>

outputs:

$d
[1] "xyz"

while

<lang R>print(a4)</lang>

outputs "xyz"


Raven

<lang raven>{ 'a' 1 'b' 2 'c' 3.14 'd' 'xyz' } as a_hash a_hash print

hash (4 items)

a => 1
b => 2
c => 3.14
d => "xyz"

a_hash 'c' get # get key 'c' 6.28 a_hash 'c' set # set key 'c' a_hash.'c' # get key 'c' shorthand 6.28 a_hash:'c' # set key 'c' shorthand</lang>

Null is returned for unknown keys.

Retro

<lang Retro>with hashTable' hashTable constant table

table %{ first = 100 }% table %{ second = "hello, world!" keepString %}

table @" first" putn table @" second" puts</lang>

REXX

Associative arrays are called stem variables in Rexx. <lang Rexx>/* Rexx */

key0 = '0' key1 = 'key0'

stem. = '.' /* Initialize the associative array 'stem' to '.' */ stem.key1 = 'value0' /* Set a specific key/value pair */

Say '<stem key="'key0'" value="'stem.key0'" />' /* Display a value for a key that wasn't set */ Say '<stem key="'key1'" value="'stem.key1'" />' /* Display a value for a key that was set */ </lang>

RLaB

Associative arrays are called lists in RLaB. <lang RLaB> x = <<>>; // create an empty list using strings as identifiers. x.red = strtod("0xff0000"); // RLaB doesn't deal with hexadecimal numbers directly. Thus we x.green = strtod("0x00ff00"); // convert it to real numbers using strtod function. x.blue = strtod("0x0000ff");

// print content of a list for (i in members(x)) { printf("%8s %06x\n", i, int(x.[i])); } // we have to use int function to convert reals to integers so "%x" format works

// deleting a key/value clear (x.red);

// we can also use numeric identifiers in the above example xid = members(x); // this is a string array

for (i in 1:length(xid)) { printf("%8s %06x\n", xid[i], int(x.[ xid[i] ])); }

// Finally, we can use numerical identifiers // Note: members function orders the list identifiers lexicographically, in other words // instead of, say, 1,2,3,4,5,6,7,8,9,10,11 members returns 1,10,11,2,3,4,5,6,7,8,9 x = <<>>; // create an empty list for (i in 1:5) { x.[i] = i; } // assign to the element of list i the real value equal to i.

</lang>

Ruby

A hash object that returns nil for unknown keys <lang ruby>hash={} hash[666]='devil' hash[777] # => nil hash[666] # => 'devil'</lang>

A hash object that returns 'unknown key' for unknown keys <lang ruby>hash=Hash.new('unknown key') hash[666]='devil' hash[777] # => 'unknown key' hash[666] # => 'devil'</lang>

A hash object that returns "unknown key #{key}" for unknown keys <lang ruby>hash=Hash.new{|h,k| "unknown key #{k}"} hash[666]='devil' hash[777] # => 'unknown key 777' hash[666] # => 'devil'</lang>

A hash object that adds "key #{key} was added at #{Time.now}" to the hash the first time an unknown key is seen <lang ruby>hash=Hash.new{|h,k|h[k]="key #{k} was added at #{Time.now}"} hash[777] # => 'key 777 was added at Sun Apr 03 13:49:57 -0700 2011' hash[555] # => 'key 555 was added at Sun Apr 03 13:50:01 -0700 2011' hash[777] # => 'key 777 was added at Sun Apr 03 13:49:57 -0700 2011'</lang>

Sather

<lang sather>class MAIN is

 main is
   -- creation of a map between strings and integers
   map ::= #MAP{STR, INT};
   -- add some values
   map := map.insert("red", 0xff0000);
   map := map.insert("green", 0xff00);
   map := map.insert("blue", 0xff);
   #OUT + map + "\n"; -- show the map...
   -- test if "indexes" exist
   #OUT +  map.has_ind("red") + "\n";
   #OUT +  map.has_ind("carpet") + "\n";
   -- retrieve a value by index
   #OUT + map["green"] + "\n";
 end;

end; </lang>

Scala

<lang scala>// immutable maps var map = Map(1 -> 2, 3 -> 4, 5 -> 6) map(3) // 4 map = map + (44 -> 99) // maps are immutable, so we have to assign the result of adding elements map.isDefinedAt(33) // false map.isDefinedAt(44) // true</lang>

<lang scala>// mutable maps (HashSets) import scala.collection.mutable.HashMap val hash = new HashMap[int, int] hash(1) = 2 hash += (1 -> 2) // same as hash(1) = 2 hash += (3 -> 4, 5 -> 6, 44 -> 99) hash(44) // 99 hash.contains(33) // false hash.isDefinedAt(33) // same as contains hash.contains(44) // true</lang>

<lang scala>// iterate over key/value hash.foreach {e => println("key "+e._1+" value "+e._2)} // e is a 2 element Tuple // same with for syntax for((k,v) <- hash) println("key " + k + " value " + v)</lang>

<lang scala>// items in map where the key is greater than 3 map.filter {k => k._1 > 3} // Map(5 -> 6, 44 -> 99) // same with for syntax for((k, v) <- map; if k > 3) yield (k,v)</lang>

Scheme

Scheme has association lists (alists), which are inefficient, ordered maps with arbitrary keys and values. Hash tables are provided by SRFI-69 [1]. Many Scheme implementation also provide native hash tables.

<lang scheme> (define my-alist '((a b) (1 hello) ("c" (a b c))) (define my-hash (alist->hash-table my-alist)) </lang>

Seed7

Seed7 uses the type hash to support associative arrays.

<lang seed7>$ include "seed7_05.s7i";

  1. Define hash type

const type: myHashType is hash [string] integer;

  1. Define hash table

var myHashType: aHash is myHashType.value;

const proc: main is func

 local
   var string: stri is "";
   var integer: number is 0;
 begin
   # Add elements
   aHash @:= ["foo"] 42;
   aHash @:= ["bar"] 100;
   # Check presence of an element
   if "foo" in aHash then
     # Access an element
     writeln(aHash["foo"]);
   end if;
   # Change an element
   aHash @:= ["foo"] 7;
   # Remove an element
   excl(aHash, "foo");
   # Loop over the hash values
   for number range aHash do
     writeln(number);
   end for;
   # Loop over the hash keys
   for key stri range aHash do
     writeln(stri);
   end for;
   # Loop over hash keys and values
   for number key stri range aHash do
     writeln("key: " <& stri <& ", value: " <& number);
   end for;
 end func;</lang>

Slate

<lang slate>Dictionary new*, 'MI' -> 'Michigan', 'MN' -> 'Minnesota'</lang>

Smalltalk

<lang smalltalk>states := Dictionary new. states at: 'MI' put: 'Michigan'. states at: 'MN' put: 'Minnesota'.</lang>

SNOBOL4

<lang snobol4> t = table() t<"red"> = "#ff0000" t<"green"> = "#00ff00" t<"blue"> = "#0000ff"

output = t<"red"> output = t<"blue"> output = t<"green"> end</lang>

Tcl

All arrays in Tcl are associative.

<lang tcl># Create one element at a time: set hash(foo) 5

  1. Create in bulk:

array set hash {

   foo 5
   bar 10
   baz 15

}

  1. Access one element:

set value $hash(foo)

  1. Output all values:

foreach key [array names hash] {

   puts $hash($key)

}</lang>

Tcl also provides associative map values (called “dictionaries”) from 8.5 onwards.

Works with: Tcl version 8.5

<lang tcl># Create in bulk set d [dict create foo 5 bar 10 baz 15]

  1. Create/update one element

dict set d foo 5

  1. Access one value

set value [dict get $d foo]

  1. Output all values

dict for {key value} $d {

   puts $value

}

  1. Alternatively...

foreach value [dict values $d] {

   puts $value

}

  1. Output the whole dictionary (since it is a Tcl value itself)

puts $d</lang>

Toka

Toka provides associative arrays via a library.

<lang toka>needs asarray

( create an associative array ) 1024 cells is-asarray foo

( store 100 as the "first" element in the array ) 100 " first" foo asarray.put

( store 200 as the "second" element in the array ) 200 " second" foo asarray.put

( obtain and print the values ) " first" foo asarray.get . " second" foo asarray.get .</lang>

UnixPipes

A key value file can be considered as an associative array <lang bash>map='p.map'

function init() { cat <<EOF > $map apple a boy b cat c dog d elephant e EOF }

function put() {

   k=$1; v=$2;
   del $k
   echo $v $k >> $map
}

function get() {

   k=$1
   for v in $(cat $map | grep "$k$"); do
       echo $v
       break
   done
}

function del() {

   k=$1
   temp=$(mktemp)
   mv $map $temp
   cat $temp | grep -v "$k$" > $map

}

function dump() {

   echo "-- Dump begin --"
   cat $map
   echo "-- Dump complete --"

}

init get c put c cow get c dump</lang>