I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

Associative array/Creation

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

The goal is to create an associative array (also known as a dictionary, map, or hash).

11l

`V dict = [‘key1’ = 1, ‘key2’ = 2]V value2 = dict[‘key2’]`

8th

8th has 'maps' as built-in data types, and can use JSON to describe them:

` { "one" : 1, "two" : "bad" } `

Alternatively, they can be created in code:

` m:new "one" 1 m:! "two" "bad" m:! `

AArch64 Assembly

Works with: as version Raspberry Pi 3B version Buster 64 bits
or android 64 bits with application Termux
` /* ARM assembly AARCH64 Raspberry PI 3B or android 64 bits *//*  program hashmap64.s   */  /*******************************************//* Constantes file                         *//*******************************************//* for this file see task include a file in language AArch64 assembly*/.include "../includeConstantesARM64.inc".equ MAXI, 10.equ HEAPSIZE,20000.equ LIMIT, 10                  // key characters number for compute hash.equ COEFF, 80                  // filling rate 80 = 80%  /*******************************************//* Structures                               *//********************************************//* structure hashMap   */    .struct  0hash_count:                       //  stored values counter    .struct  hash_count + 8hash_key:                         //  key    .struct  hash_key + (8 * MAXI)hash_data:                        // data    .struct  hash_data + (8 * MAXI)hash_fin:/*********************************//* Initialized data              *//*********************************/.dataszMessFin:          .asciz "End program.\n"szCarriageReturn:   .asciz "\n"szMessNoP:          .asciz "Key not found !!!\n"szKey1:             .asciz "one"szData1:            .asciz "Ceret"szKey2:             .asciz "two"szData2:            .asciz "Maureillas"szKey3:             .asciz "three"szData3:            .asciz "Le Perthus"szKey4:             .asciz "four"szData4:            .asciz "Le Boulou" .align 4iptZoneHeap:    .quad sZoneHeap            // start heap addressiptZoneHeapEnd: .quad sZoneHeap + HEAPSIZE // end heap address/*********************************//* UnInitialized data            *//*********************************/.bsstbHashMap1:       .skip hash_fin         // hashmapsZoneHeap:        .skip HEAPSIZE         // heap/*********************************//*  code section                 *//*********************************/.text.global main main:                          // entry of program      ldr x0,qAdrtbHashMap1    bl hashInit                // init hashmap    ldr x0,qAdrtbHashMap1    ldr x1,qAdrszKey1          // store key one    ldr x2,qAdrszData1    bl hashInsert    cmp x0,#0                  // error ?    bne 100f    ldr x0,qAdrtbHashMap1    ldr x1,qAdrszKey2         // store key two    ldr x2,qAdrszData2    bl hashInsert    cmp x0,#0    bne 100f     ldr x0,qAdrtbHashMap1    ldr x1,qAdrszKey3          // store key three    ldr x2,qAdrszData3    bl hashInsert    cmp x0,#0    bne 100f    ldr x0,qAdrtbHashMap1    ldr x1,qAdrszKey4          // store key four    ldr x2,qAdrszData4    bl hashInsert    cmp x0,#0    bne 100f     ldr x0,qAdrtbHashMap1    ldr x1,qAdrszKey2          // remove key two    bl hashRemoveKey    cmp x0,#0    bne 100f     ldr x0,qAdrtbHashMap1    ldr x1,qAdrszKey1          // search key one    bl searchKey    cmp x0,#-1    beq 1f    bl affichageMess    ldr x0,qAdrszCarriageReturn    bl affichageMess    b 2f1:    ldr x0,qAdrszMessNoP    bl affichageMess2:    ldr x0,qAdrtbHashMap1    ldr x1,qAdrszKey2          // search key two    bl searchKey    cmp x0,#-1    beq 3f    bl affichageMess    ldr x0,qAdrszCarriageReturn    bl affichageMess    b 4f3:    ldr x0,qAdrszMessNoP    bl affichageMess4:    ldr x0,qAdrtbHashMap1    ldr x1,qAdrszKey4          // search key four    bl searchKey    cmp x0,#-1    beq 5f    bl affichageMess    ldr x0,qAdrszCarriageReturn    bl affichageMess    b 6f5:    ldr x0,qAdrszMessNoP    bl affichageMess6:    ldr x0,qAdrszMessFin    bl affichageMess 100:                                  // standard end of the program     mov x0, #0                        // return code    mov x8, #EXIT                     // request to exit program    svc #0                            // perform the system call qAdrszCarriageReturn:     .quad szCarriageReturnqAdrszMessFin:            .quad szMessFinqAdrtbHashMap1:           .quad tbHashMap1qAdrszKey1:               .quad szKey1qAdrszData1:              .quad szData1qAdrszKey2:               .quad szKey2qAdrszData2:              .quad szData2qAdrszKey3:               .quad szKey3qAdrszData3:              .quad szData3qAdrszKey4:               .quad szKey4qAdrszData4:              .quad szData4qAdrszMessNoP:            .quad szMessNoP/***************************************************//*     init hashMap               *//***************************************************/// x0 contains address to hashMaphashInit:    stp x1,lr,[sp,-16]!         // save  registres    stp x2,x3,[sp,-16]!         // save  registres    mov x1,#0    mov x2,#0    str x2,[x0,#hash_count]      // init counter    add x0,x0,#hash_key         // start zone key/value1:    lsl x3,x1,#3    add x3,x3,x0    str x2,[x3,#hash_key]    str x2,[x3,#hash_data]    add x1,x1,#1    cmp x1,#MAXI    blt 1b100:    ldp x2,x3,[sp],16         // restaur des  2 registres    ldp x1,lr,[sp],16         // restaur des  2 registres    ret/***************************************************//*     insert key/datas               *//***************************************************/// x0 contains address to hashMap// x1 contains address to key// x2 contains address to datashashInsert:    stp x1,lr,[sp,-16]!         // save  registres    stp x2,x3,[sp,-16]!         // save  registres    stp x4,x5,[sp,-16]!         // save  registres    stp x6,x7,[sp,-16]!         // save  registres    mov x6,x0                   // save address     bl hashIndex                // search void key or identical key    cmp x0,#0                   // error ?    blt 100f     ldr x3,qAdriptZoneHeap    ldr x3,[x3]    ldr x7,qAdriptZoneHeapEnd    ldr x7,[x7]    sub x7,x7,#50    lsl x0,x0,#3               // 8 bytes    add x5,x6,#hash_key        // start zone key/value    ldr x4,[x5,x0]    cmp x4,#0                  // key already stored ?    bne 1f    ldr x4,[x6,#hash_count]    // no -> increment counter    add x4,x4,#1    cmp x4,#(MAXI * COEFF / 100)    bge 98f    str x4,[x6,#hash_count]1:    str x3,[x5,x0]            // store heap key address in hashmap    mov x4,#02:                            // copy key loop in heap    ldrb w5,[x1,x4]    strb w5,[x3,x4]    cmp w5,#0    add x4,x4,#1    bne 2b    add x3,x3,x4    cmp x3,x7    bge 99f    add x1,x6,#hash_data    str x3,[x1,x0]           // store heap data address in hashmap    mov x4,#03:                            // copy data loop in heap    ldrb w5,[x2,x4]    strb w5,[x3,x4]    cmp w5,#0    add x4,x4,#1    bne 3b    add x3,x3,x4    cmp x3,x7    bge 99f    ldr x0,qAdriptZoneHeap    str x3,[x0]               // new heap address     mov x0,#0                 // insertion OK    b 100f98:                           // error hashmap    adr x0,szMessErrInd    bl affichageMess    mov x0,#-1    b 100f99:                           // error heap    adr x0,szMessErrHeap    bl affichageMess    mov x0,#-1100:    ldp x6,x7,[sp],16         // restaur des  2 registres    ldp x4,x5,[sp],16         // restaur des  2 registres    ldp x2,x3,[sp],16         // restaur des  2 registres    ldp x1,lr,[sp],16         // restaur des  2 registres    retszMessErrInd:          .asciz "Error : HashMap size Filling rate Maxi !!\n"szMessErrHeap:         .asciz "Error : Heap size  Maxi !!\n".align 4qAdriptZoneHeap:       .quad iptZoneHeapqAdriptZoneHeapEnd:    .quad iptZoneHeapEnd/***************************************************//*     search void index in hashmap              *//***************************************************/// x0 contains hashMap address // x1 contains key addresshashIndex:    stp x1,lr,[sp,-16]!         // save  registres    stp x2,x3,[sp,-16]!         // save  registres    stp x4,x5,[sp,-16]!         // save  registres    add x4,x0,#hash_key    mov x2,#0             // index    mov x3,#0             // characters sum 1:                        // loop to compute characters sum     ldrb w0,[x1,x2]    cmp w0,#0             // string end ?    beq 2f    add x3,x3,x0          // add to sum    add x2,x2,#1    cmp x2,#LIMIT    blt 1b2:    mov x5,x1             // save key address    mov x0,x3    mov x1,#MAXI    udiv x2,x0,x1    msub x3,x2,x1,x0           // compute remainder -> x3    mov x1,x5             // key address 3:    ldr x0,[x4,x3,lsl #3] // loak key for computed index     cmp x0,#0             // void key ?    beq 4f     bl comparStrings      // identical key ?    cmp x0,#0    beq 4f                // yes    add x3,x3,#1          // no search next void key    cmp x3,#MAXI          // maxi ?    csel x3,xzr,x3,ge     // restart to index 0    b 3b4:    mov x0,x3             // return index void array or key equal100:    ldp x4,x5,[sp],16         // restaur des  2 registres    ldp x2,x3,[sp],16         // restaur des  2 registres    ldp x1,lr,[sp],16         // restaur des  2 registres    ret /***************************************************//*     search key in hashmap              *//***************************************************/// x0 contains hash map address// x1 contains key addresssearchKey:    stp x1,lr,[sp,-16]!         // save  registres    stp x2,x3,[sp,-16]!         // save  registres    mov x2,x0    bl hashIndex    lsl x0,x0,#3    add x1,x0,#hash_key    ldr x1,[x2,x1]    cmp x1,#0    beq 2f    add x1,x0,#hash_data    ldr x0,[x2,x1]    b 100f2:    mov x0,#-1100:    ldp x2,x3,[sp],16         // restaur des  2 registres    ldp x1,lr,[sp],16         // restaur des  2 registres    ret/***************************************************//*     remove key in hashmap              *//***************************************************/// x0 contains hash map address// x1 contains key addresshashRemoveKey:    stp x1,lr,[sp,-16]!         // save  registres    stp x2,x3,[sp,-16]!         // save  registres    mov x2,x0    bl hashIndex    lsl x0,x0,#3    add x1,x0,#hash_key    ldr x3,[x2,x1]    cmp x3,#0    beq 2f    str xzr,[x2,x1]            // raz key address    add x1,x0,#hash_data    str xzr,[x2,x1]            // raz datas address    mov x0,0    b 100f2:    adr x0,szMessErrRemove    bl affichageMess    mov x0,#-1100:    ldp x2,x3,[sp],16         // restaur des  2 registres    ldp x1,lr,[sp],16         // restaur des  2 registres    ret szMessErrRemove:         .asciz "\033[31mError remove key !!\033[0m\n".align 4/************************************/	   /* Strings case sensitive comparisons  *//************************************/	  /* x0 et x1 contains the address of strings *//* return 0 in x0 if equals *//* return -1 if string x0 < string x1 *//* return 1  if string x0 > string x1 */comparStrings:    stp x1,lr,[sp,-16]!  // save  registres    stp x2,x3,[sp,-16]!  // save  registres    stp x4,x5,[sp,-16]!  // save  registres    mov x2,#0            // characters counter1:    ldrb w3,[x0,x2]      // byte string 1    ldrb w4,[x1,x2]      // byte string 2    cmp w3,w4    blt 2f    bgt 3f    cmp w3,#0            // 0 end string ?    beq 4f    add x2,x2,#1         // else add 1 in counter    b 1b                 // and loop2:    mov x0,#-1           // smaller    b 100f3:    mov x0,#1            // greather    b 100f4:    mov x0,#0           // equals100:      ldp x4,x5,[sp],16   // restaur des  2 registres    ldp x2,x3,[sp],16   // restaur des  2 registres    ldp x1,lr,[sp],16   // restaur des  2 registres    ret/********************************************************//*        File Include fonctions                        *//********************************************************//* for this file see task include a file in language AArch64 assembly */.include "../includeARM64.inc"  `

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.

`var map:Object = {key1: "value1", key2: "value2"};trace(map['key1']); // outputs "value1" // Dot notation can also be usedtrace(map.key2); // outputs "value2" // More keys and values can then be addedmap['key3'] = "value3";trace(map['key3']); // outputs "value3"`

Note: The Object only supports String keys. To use an object as a key, try the flash.utils.Dictionary class.

Works with: GNAT version GPL 2007
`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;`

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.

` var names = {}   // empty mapnames["foo"] = "bar"names[3] = 4 // initialized mapvar names2 = {"foo": bar, 3:4} // lookup mapvar name = names["foo"]if (typeof(name) == "none") {    println ("not found")} else {    println (name)} // remove from mapdelete names["foo"]   `

Aime

Aime records are heterogenous associative arrays. No creation procedure is required, declaration is fine.

`record r;`
`r_put(r, "A", 33);		# an integer valuer_put(r, "C", 2.5);		# a real valuer_put(r, "B", "associative");	# a string value`

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
`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;# 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\$)) )`
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)
```

Apex

Apex provides a Map datatype that maps unique keys to a single value. Both keys and values can be any data type, including user-defined types. Like Java, equals and hashCode are used to determine key uniqueness for user-defined types. Uniqueness of sObject keys is determined by comparing field values.

Creating a new empty map of String to String:

`// Cannot / Do not need to instantiate the algorithm implementation (e.g, HashMap).Map<String, String> strMap = new Map<String, String>();strMap.put('a', 'aval');strMap.put('b', 'bval'); System.assert( strMap.containsKey('a') );System.assertEquals( 'bval', strMap.get('b') );// String keys are case-sensitiveSystem.assert( !strMap.containsKey('A') );`

Creating a new map of String to String with values initialized:

`Map<String, String> strMap = new Map<String, String>{  'a' => 'aval',  'b' => 'bval'}; System.assert( strMap.containsKey('a') );System.assertEquals( 'bval', strMap.get('b') );`

APL

Works with: Dyalog APL
`⍝  Create a namespace ("hash")      X←⎕NS ⍬       ⍝ Assign some names      X.this←'that'      X.foo←88       ⍝  Access the names      X.thisthat       ⍝  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.revenue4109.6 `
Works with: GNU APL
`       ⍝ Assign some names      X.this←'that'      X.foo←88       ⍝  Access the names      X.thisthat       ⍝  ..or access via 'array index' syntax      X['this']that       ⍝  Or do it the array way      X.(foo)88       ⍝ GNU APL does not support multiple assoc. array indices however      X.(foo this)VALUE ERROR      X.(foo this)             ^       (sales.prices sales.quantities) ← (100 98.4 103.4 110.16) (10 12 8 10)      sales.revenue ← sales.prices +.× sales.quantities      sales.revenue4109.6 `

App Inventor

Associative arrays in App Inventor are lists of key:value 'pairs'.
When a list is organized as pairs, the lookup in pairs block can be used to retrieve an associated value from a key name.
<VIEW BLOCKS AND ANDROID APP>

ARM Assembly

Works with: as version Raspberry Pi
or android 32 bits with application Termux
` /* ARM assembly Raspberry PI  or android 32 bits *//*  program hashmap.s   */  /*      */ /* REMARK 1 : this program use routines in a include file    see task Include a file language arm assembly    for the routine affichageMess conversion10    see at end of this program the instruction include *//* for constantes see task include a file in arm assembly *//************************************//* Constantes                       *//************************************/.include "../constantes.inc".equ MAXI, 10                   @ size hashmap.equ HEAPSIZE,20000.equ LIMIT, 10                  @ key characters number for compute index.equ COEFF, 80                  @ filling rate 80 = 80%  /*******************************************//* Structures                               *//********************************************//* structure hashMap   */    .struct  0hash_count:                       //  stored values counter    .struct  hash_count + 4hash_key:                         //  key    .struct  hash_key + (4 * MAXI)hash_data:                        // data    .struct  hash_data + (4 * MAXI)hash_fin:/*********************************//* Initialized data              *//*********************************/.dataszMessFin:          .asciz "End program.\n"szCarriageReturn:   .asciz "\n"szMessNoP:          .asciz "Key not found !!!\n"szKey1:             .asciz "one"szData1:            .asciz "Ceret"szKey2:             .asciz "two"szData2:            .asciz "Maureillas"szKey3:             .asciz "three"szData3:            .asciz "Le Perthus"szKey4:             .asciz "four"szData4:            .asciz "Le Boulou" .align 4iptZoneHeap:    .int sZoneHeap            // start heap addressiptZoneHeapEnd: .int sZoneHeap + HEAPSIZE // end heap address/*********************************//* UnInitialized data            *//*********************************/.bss//sZoneConv:        .skip 24tbHashMap1:       .skip hash_fin         @ hashmapsZoneHeap:        .skip HEAPSIZE         @ heap/*********************************//*  code section                 *//*********************************/.text.global main main:                          @ entry of program      ldr r0,iAdrtbHashMap1    bl hashInit                @ init hashmap    ldr r0,iAdrtbHashMap1    ldr r1,iAdrszKey1          @ store key one    ldr r2,iAdrszData1    bl hashInsert    cmp r0,#0                  @ error ?    bne 100f    ldr r0,iAdrtbHashMap1    ldr r1,iAdrszKey2          @ store key two    ldr r2,iAdrszData2    bl hashInsert    cmp r0,#0    bne 100f    ldr r0,iAdrtbHashMap1    ldr r1,iAdrszKey3          @ store key three    ldr r2,iAdrszData3    bl hashInsert    cmp r0,#0    bne 100f    ldr r0,iAdrtbHashMap1    ldr r1,iAdrszKey4          @ store key four    ldr r2,iAdrszData4    bl hashInsert    cmp r0,#0    bne 100f     ldr r0,iAdrtbHashMap1    ldr r1,iAdrszKey2          @ remove key two    bl hashRemoveKey    cmp r0,#0    bne 100f     ldr r0,iAdrtbHashMap1    ldr r1,iAdrszKey1         @ search key    bl searchKey    cmp r0,#-1    beq 1f    bl affichageMess    ldr r0,iAdrszCarriageReturn    bl affichageMess    b 2f1:    ldr r0,iAdrszMessNoP    bl affichageMess2:    ldr r0,iAdrtbHashMap1    ldr r1,iAdrszKey2    bl searchKey    cmp r0,#-1    beq 3f    bl affichageMess    ldr r0,iAdrszCarriageReturn    bl affichageMess    b 4f3:    ldr r0,iAdrszMessNoP    bl affichageMess4:    ldr r0,iAdrtbHashMap1    ldr r1,iAdrszKey4    bl searchKey    cmp r0,#-1    beq 5f    bl affichageMess    ldr r0,iAdrszCarriageReturn    bl affichageMess    b 6f5:    ldr r0,iAdrszMessNoP    bl affichageMess6:    ldr r0,iAdrszMessFin    bl affichageMess 100:                                  @ standard end of the program     mov r0, #0                        @ return code    mov r7, #EXIT                     @ request to exit program    svc #0                            @ perform the system call iAdrszCarriageReturn:     .int szCarriageReturniAdrszMessFin:            .int szMessFiniAdrtbHashMap1:           .int tbHashMap1iAdrszKey1:               .int szKey1iAdrszData1:              .int szData1iAdrszKey2:               .int szKey2iAdrszData2:              .int szData2iAdrszKey3:               .int szKey3iAdrszData3:              .int szData3iAdrszKey4:               .int szKey4iAdrszData4:              .int szData4iAdrszMessNoP:            .int szMessNoP/***************************************************//*     init hashMap               *//***************************************************/// r0 contains address to hashMaphashInit:    push {r1-r3,lr}             @ save  registers     mov r1,#0    mov r2,#0    str r2,[r0,#hash_count]      @ init counter    add r0,r0,#hash_key         @ start zone key/value1:    lsl r3,r1,#3    add r3,r3,r0    str r2,[r3,#hash_key]    str r2,[r3,#hash_data]    add r1,r1,#1    cmp r1,#MAXI    blt 1b100:    pop {r1-r3,pc}             @ restaur registers/***************************************************//*     insert key/datas               *//***************************************************/// r0 contains address to hashMap// r1 contains address to key// r2 contains address to datashashInsert:    push {r1-r8,lr}             @ save  registers     mov r6,r0                   @ save address     bl hashIndex                @ search void key or identical key    cmp r0,#0                   @ error ?    blt 100f     ldr r3,iAdriptZoneHeap    ldr r3,[r3]    ldr r8,iAdriptZoneHeapEnd    ldr r8,[r8]    sub r8,r8,#50    lsl r0,r0,#2               @ 4 bytes    add r7,r6,#hash_key        @ start zone key/value    ldr r4,[r7,r0]    cmp r4,#0                  @ key already stored ?    bne 1f    ldr r4,[r6,#hash_count]    @ no -> increment counter    add r4,r4,#1    cmp r4,#(MAXI * COEFF / 100)    bge 98f    str r4,[r6,#hash_count]1:    str r3,[r7,r0]    mov r4,#02:                            @ copy key loop in heap    ldrb r5,[r1,r4]    strb r5,[r3,r4]    cmp r5,#0    add r4,r4,#1    bne 2b    add r3,r3,r4    cmp r3,r8    bge 99f    add r7,r6,#hash_data    str r3,[r7,r0]    mov r4,#03:                            @ copy data loop in heap    ldrb r5,[r2,r4]    strb r5,[r3,r4]    cmp r5,#0    add r4,r4,#1    bne 3b    add r3,r3,r4    cmp r3,r8    bge 99f    ldr r0,iAdriptZoneHeap    str r3,[r0]               @ new heap address     mov r0,#0                 @ insertion OK    b 100f98:                           @ error hashmap    adr r0,szMessErrInd    bl affichageMess    mov r0,#-1    b 100f99:                           @ error heap    adr r0,szMessErrHeap    bl affichageMess    mov r0,#-1100:    pop {r1-r8,lr}             @ restaur registers    bx lr                      @ returnszMessErrInd:          .asciz "Error : HashMap size Filling rate Maxi !!\n"szMessErrHeap:         .asciz "Error : Heap size  Maxi !!\n".align 4iAdriptZoneHeap:       .int iptZoneHeapiAdriptZoneHeapEnd:    .int iptZoneHeapEnd/***************************************************//*     search void index in hashmap              *//***************************************************/// r0 contains hashMap address // r1 contains key addresshashIndex:    push {r1-r4,lr}       @ save  registers     add r4,r0,#hash_key    mov r2,#0             @ index    mov r3,#0             @ characters sum 1:                        @ loop to compute characters sum     ldrb r0,[r1,r2]    cmp r0,#0             @ string end ?    beq 2f    add r3,r3,r0          @ add to sum    add r2,r2,#1    cmp r2,#LIMIT    blt 1b2:    mov r5,r1             @ save key address    mov r0,r3    mov r1,#MAXI    bl division           @ compute remainder -> r3    mov r1,r5             @ key address 3:    ldr r0,[r4,r3,lsl #2] @ loak key for computed index     cmp r0,#0             @ void key ?    beq 4f     bl comparStrings      @ identical key ?    cmp r0,#0    beq 4f                @ yes    add r3,r3,#1          @ no search next void key    cmp r3,#MAXI          @ maxi ?    movge r3,#0           @ restart to index 0    b 3b4:    mov r0,r3             @ return index void array or key equal100:    pop {r1-r4,pc}        @ restaur registers /***************************************************//*     search key in hashmap              *//***************************************************/// r0 contains hash map address// r1 contains key addresssearchKey:    push {r1-r2,lr}           @ save  registers     mov r2,r0    bl hashIndex    lsl r0,r0,#2    add r1,r0,#hash_key    ldr r1,[r2,r1]    cmp r1,#0    moveq r0,#-1    beq 100f    add r1,r0,#hash_data    ldr r0,[r2,r1]100:    pop {r1-r2,pc}            @ restaur registers/***************************************************//*     remove key in hashmap              *//***************************************************/// r0 contains hash map address// r1 contains key addresshashRemoveKey:                  @ INFO: hashRemoveKey    push {r1-r3,lr}             @ save  registers     mov r2,r0    bl hashIndex    lsl r0,r0,#2    add r1,r0,#hash_key    ldr r3,[r2,r1]    cmp r3,#0    beq  2f    add r3,r2,r1    mov r1,#0                   @ raz key address    str r1,[r3]       add r1,r0,#hash_data    add r3,r2,r1    mov r1,#0    str r1,[r3]                 @ raz datas address    mov r0,#0    b 100f2:    adr r0,szMessErrRemove    bl affichageMess    mov r0,#-1100:    pop {r1-r3,pc}            @ restaur registersszMessErrRemove:         .asciz "\033[31mError remove key !!\033[0m\n".align 4/************************************/   /* Strings case sensitive comparisons  *//************************************/	  /* r0 et r1 contains the address of strings *//* return 0 in r0 if equals *//* return -1 if string r0 < string r1 *//* return 1  if string r0 > string r1 */comparStrings:    push {r1-r4}         @ save des registres    mov r2,#0            @ characters counter1:    ldrb r3,[r0,r2]      @ byte string 1    ldrb r4,[r1,r2]      @ byte string 2    cmp r3,r4    movlt r0,#-1         @ smaller    movgt r0,#1	         @ greather    bne 100f             @ not equals    cmp r3,#0            @ 0 end string ?    moveq r0,#0          @ equals    beq 100f             @ end string    add r2,r2,#1         @ else add 1 in counter    b 1b                 @ and loop100:    pop {r1-r4}    bx lr   /***************************************************//*      ROUTINES INCLUDE                           *//***************************************************/.include "../affichage.inc"  `

Arturo

`; create a dictionaryd: #[	name: 		"john"	surname: 	"doe"	age: 		34] print d`
Output:
`[name:john surname:doe age:34]`

ATS

ATS, like many languages, does not have high level stuff such as maps built into the language itself, so library support or one's own code is what one needs.

In the following, persistence means that past values of the map are retained, if they continue to have references to them. This property sometimes is called immutability, but I feel that term implies too much.

Persistent association lists

The following implementation includes set, get, and delete, and also "generators", which are like iterators except they are closures rather than regular objects.

`(*------------------------------------------------------------------*) #define ATS_DYNLOADFLAG 0 #include "share/atspre_staload.hats" (*------------------------------------------------------------------*)(* Interface                                                        *) (* You can put the interface in a .sats file. You will have to remove   the word "extern". *) typedef alist_t (key_t  : [email protected]+,                 data_t : [email protected]+,                 size   : int) =  list (@(key_t, data_t), size)typedef alist_t (key_t  : [email protected]+,                 data_t : [email protected]+) =  [size : int]  alist_t (key_t, data_t, size) extern prfunlemma_alist_t_param :  {size  : int} {key_t : [email protected]} {data_t : [email protected]}  alist_t (key_t, data_t, size) -<prf> [0 <= size] void extern fun {key_t : [email protected]}     (* Implement key equality with this. *)alist_t\$key_eq : (key_t, key_t) -<> bool (* alist_t_nil: create an empty association list. *)extern funalist_t_nil :  {key_t : [email protected]} {data_t : [email protected]}  () -<> alist_t (key_t, data_t, 0) (* alist_t_set: add an association, deleting old associations with an   equal key. *)extern fun {key_t  : [email protected]}           {data_t : [email protected]}alist_t_set {size : int}            (alst : alist_t (key_t, data_t, size),             key  : key_t,             data : data_t) :<>    [sz : int | 1 <= sz]    alist_t (key_t, data_t, sz) (* alist_t_get: find an association and return its data, if   present. *)extern fun {key_t  : [email protected]}           {data_t : [email protected]}alist_t_get {size : int}            (alst : alist_t (key_t, data_t, size),             key  : key_t) :<>    Option data_t (* alist_t_delete: delete all associations with key. *)extern fun {key_t  : [email protected]}           {data_t : [email protected]}alist_t_delete {size : int}               (alst : alist_t (key_t, data_t, size),                key  : key_t ) :<>    [sz : int | 0 <= sz]    alist_t (key_t, data_t, sz) (* alist_t_make_pairs_generator: make a closure that returns   the association pairs, one by one. This is a form of iterator.   Analogous generators can be made for the keys or data values   alone. *)extern fun {key_t  : [email protected]}           {data_t : [email protected]}alist_t_make_pairs_generator          {size : int}          (alst : alist_t (key_t, data_t, size)) :<!wrt>    () -<cloref,!refwrt> Option @(key_t, data_t) (*------------------------------------------------------------------*)(* Implementation                                                   *) #define NIL list_nil ()#define :: list_cons primplementlemma_alist_t_param alst =  lemma_list_param alst implementalist_t_nil () =  NIL implement {key_t} {data_t}alist_t_set (alst, key, data) =  @(key, data) :: alist_t_delete (alst, key) implement {key_t} {data_t}alist_t_get (alst, key) =  let    fun    loop {n : nat}         .<n>.                  (* <-- proof of termination *)         (lst : alist_t (key_t, data_t, n)) :<>        Option data_t =      case+ lst of      | NIL => None ()      | head :: tail =>        if alist_t\$key_eq (key, head.0) then          Some (head.1)        else          loop tail     prval _ = lemma_alist_t_param alst  in    loop alst  end implement {key_t} {data_t}alist_t_delete (alst, key) =  let    fun    delete {n : nat}           .<n>.                (* <-- proof of termination *)           (lst : alist_t (key_t, data_t, n)) :<>        [m : nat] alist_t (key_t, data_t, m) =      (* This implementation is *not* tail recursive, but has the         minor advantage of preserving the order of entries without         doing a lot of work. *)      case+ lst of      | NIL => lst      | head :: tail =>        if alist_t\$key_eq (key, head.0) then          delete tail        else          head :: delete tail     prval _ = lemma_alist_t_param alst  in    delete alst  end implement {key_t} {data_t}alist_t_make_pairs_generator alst =  let    typedef alist_t = [sz : int] alist_t (key_t, data_t, sz)     val alst_ref = ref alst     (* Cast the ref to a pointer so it can be enclosed in the       closure. *)    val alst_ptr = \$UNSAFE.castvwtp0{ptr} alst_ref  in    lam () =>      let        val alst_ref = \$UNSAFE.castvwtp0{ref alist_t} alst_ptr      in        case+ !alst_ref of        | NIL => None ()        | head :: tail =>          begin            !alst_ref := tail;            (* For a keys generator, change the following line to               "Some (head.0)"; for a data values generator, change               it to "Some (head.1)". *)            Some head          end      end  end (*------------------------------------------------------------------*)(* Demonstration program                                            *) implementalist_t\$key_eq<string> (s, t) =  s = t typedef s2i_alist_t = alist_t (string, int) fns2i_alist_t_set (map  : s2i_alist_t,                 key  : string,                 data : int) :<> s2i_alist_t =  alist_t_set<string><int> (map, key, data) fns2i_alist_t_set_ref (map  : &s2i_alist_t >> _,                     key  : string,                     data : int) :<!wrt> void =  (* Update a reference to a persistent alist. *)  map := s2i_alist_t_set (map, key, data) fns2i_alist_t_get (map  : s2i_alist_t,                 key  : string) :<> Option int =  alist_t_get<string><int> (map, key) extern fun {}        (* {} = a template without template parameters *)s2i_alist_t_get_dflt\$dflt :<> () -> intfn {}                (* {} = a template without template parameters *)s2i_alist_t_get_dflt (map  : s2i_alist_t,                      key  : string) : int =  case+ s2i_alist_t_get (map, key) of  | Some x => x  | None () => s2i_alist_t_get_dflt\$dflt<> () overload [] with s2i_alist_t_set_refoverload [] with s2i_alist_t_get_dflt implementmain0 () =  let    implement s2i_alist_t_get_dflt\$dflt<> () = 0    var map = alist_t_nil ()    var gen : () -<cloref1> @(string, int)    var pair : Option @(string, int)  in    map["one"] := 1;    map["two"] := 2;    map["three"] := 3;    println! ("map[\"one\"] = ", map["one"]);    println! ("map[\"two\"] = ", map["two"]);    println! ("map[\"three\"] = ", map["three"]);    println! ("map[\"four\"] = ", map["four"]);    gen := alist_t_make_pairs_generator<string><int> map;    for (pair := gen (); option_is_some pair; pair := gen ())      println! (pair)  end (*------------------------------------------------------------------*)`
Output:
```\$ patscc -O2 -DATS_MEMALLOC_GCBDW association_lists-postiats.dats -lgc && ./a.out
map["one"] = 1
map["two"] = 2
map["three"] = 3
map["four"] = 0
Some((three, 3))
Some((two, 2))
Some((one, 1))```

Persistent hashmaps based on AVL trees

Translation of: Scheme
Library: xxHash

The following implementation includes set and get, and also "generators", which are like iterators except they are closures rather than regular objects. A delete function could easily be added.

To run this demonstration you need the xxHash C library. I have written an implementation of SpookyHash in ATS, but using a C library is fine, and requires less ATS code.

Because the hash table is an AVL tree, performance will tend to be logarithmic. This assumes a good hash function, of course. With a bad hash function, performance may be linear.

`(*------------------------------------------------------------------*) #define ATS_DYNLOADFLAG 0 #include "share/atspre_staload.hats" (*------------------------------------------------------------------*)(* String hashing using XXH3_64bits from the xxHash suite.          *) #define ATS_EXTERN_PREFIX "hashmaps_postiats_" %{^ /* Embedded C code. */ #include <xxhash.h> ATSinline() atstype_uint64hashmaps_postiats_mem_hash (atstype_ptr data, atstype_size len){  return (atstype_uint64) XXH3_64bits (data, len);} %} extern fn mem_hash : (ptr, size_t) -<> uint64 = "mac#%" fnstring_hash (s : string) :<> uint64 =  let    val len = string_length s  in    mem_hash (\$UNSAFE.cast{ptr} s, len)  end (*------------------------------------------------------------------*)(* A trimmed down version of the AVL trees from the AVL Tree task.  *) datatype bal_t =| bal_minus1| bal_zero| bal_plus1 datatype avl_t (key_t  : [email protected]+,                data_t : [email protected]+,                size   : int) =| avl_t_nil (key_t, data_t, 0)| {size_L, size_R : nat}  avl_t_cons (key_t, data_t, size_L + size_R + 1) of    (key_t, data_t, bal_t,     avl_t (key_t, data_t, size_L),     avl_t (key_t, data_t, size_R))typedef avl_t (key_t  : [email protected]+,               data_t : [email protected]+) =  [size : int] avl_t (key_t, data_t, size) extern fun {key_t : [email protected]}avl_t\$compare (u : key_t, v : key_t) :<> int #define NIL avl_t_nil ()#define CONS avl_t_cons#define LNIL list_nil ()#define :: list_cons#define F false#define T true typedef fixbal_t = bool prfnlemma_avl_t_param {key_t : [email protected]} {data_t : [email protected]} {size : int}                  (avl : avl_t (key_t, data_t, size)) :<prf>    [0 <= size] void =  case+ avl of NIL => () | CONS _ => () fn {}minus_neg_bal (bal : bal_t) :<> bal_t =  case+ bal of  | bal_minus1 () => bal_plus1  | _ => bal_zero () fn {}minus_pos_bal (bal : bal_t) :<> bal_t =  case+ bal of  | bal_plus1 () => bal_minus1  | _ => bal_zero () fnavl_t_is_empty {key_t : [email protected]} {data_t : [email protected]} {size   : int}               (avl : avl_t (key_t, data_t, size)) :<>    [b : bool | b == (size == 0)] bool b =  case+ avl of  | NIL => T  | CONS _ => F fnavl_t_isnot_empty {key_t : [email protected]} {data_t : [email protected]} {size   : int}                  (avl : avl_t (key_t, data_t, size)) :<>    [b : bool | b == (size <> 0)] bool b =  ~avl_t_is_empty avl fn {key_t : [email protected]} {data_t : [email protected]}avl_t_search_ref {size  : int}                 (avl   : avl_t (key_t, data_t, size),                  key   : key_t,                  data  : &data_t? >> opt (data_t, found),                  found : &bool? >> bool found) :<!wrt>    #[found : bool] void =  let    fun    search (p     : avl_t (key_t, data_t),            data  : &data_t? >> opt (data_t, found),            found : &bool? >> bool found) :<!wrt,!ntm>        #[found : bool] void =      case+ p of      | NIL =>        {          prval _ = opt_none {data_t} data          val _ = found := F        }      | CONS (k, d, _, left, right) =>        begin          case+ avl_t\$compare<key_t> (key, k) of          | cmp when cmp < 0 => search (left, data, found)          | cmp when cmp > 0 => search (right, data, found)          | _ =>            {              val _ = data := d              prval _ = opt_some {data_t} data              val _ = found := T            }        end  in    \$effmask_ntm search (avl, data, found)  end fn {key_t : [email protected]} {data_t : [email protected]}avl_t_search_opt {size : int}                 (avl  : avl_t (key_t, data_t, size),                  key  : key_t) :<>    Option (data_t) =  let    var data : data_t?    var found : bool?    val _ = \$effmask_wrt avl_t_search_ref (avl, key, data, found)  in    if found then      let        prval _ = opt_unsome data      in        Some {data_t} data      end    else      let        prval _ = opt_unnone data      in        None {data_t} ()      end  end fn {key_t : [email protected]} {data_t : [email protected]}avl_t_insert_or_replace {size : int}                        (avl  : avl_t (key_t, data_t, size),                         key  : key_t,                         data : data_t) :<>    [sz : pos] (avl_t (key_t, data_t, sz), bool) =  let    fun    search {size   : nat}           (p      : avl_t (key_t, data_t, size),            fixbal : fixbal_t,            found  : bool) :<!ntm>        [sz : pos]        (avl_t (key_t, data_t, sz), fixbal_t, bool) =      case+ p of      | NIL => (CONS (key, data, bal_zero, NIL, NIL), T, F)      | CONS (k, d, bal, left, right) =>        case+ avl_t\$compare<key_t> (key, k) of        | cmp when cmp < 0 =>          let            val (p1, fixbal, found) = search (left, fixbal, found)          in            case+ (fixbal, bal) of            | (F, _) => (CONS (k, d, bal, p1, right), F, found)            | (T, bal_plus1 ()) =>              (CONS (k, d, bal_zero (), p1, right), F, found)            | (T, bal_zero ()) =>              (CONS (k, d, bal_minus1 (), p1, right), fixbal, found)            | (T, bal_minus1 ()) =>              let                val+ CONS (k1, d1, bal1, left1, right1) = p1              in                case+ bal1 of                | bal_minus1 () =>                  let                    val q = CONS (k, d, bal_zero (), right1, right)                    val q1 = CONS (k1, d1, bal_zero (), left1, q)                  in                    (q1, F, found)                  end                | _ =>                  let                    val p2 = right1                    val- CONS (k2, d2, bal2, left2, right2) = p2                    val q = CONS (k, d, minus_neg_bal bal2,                                  right2, right)                    val q1 = CONS (k1, d1, minus_pos_bal bal2,                                   left1, left2)                    val q2 = CONS (k2, d2, bal_zero (), q1, q)                  in                    (q2, F, found)                  end              end          end        | cmp when cmp > 0 =>          let            val (p1, fixbal, found) = search (right, fixbal, found)          in            case+ (fixbal, bal) of            | (F, _) => (CONS (k, d, bal, left, p1), F, found)            | (T, bal_minus1 ()) =>              (CONS (k, d, bal_zero (), left, p1), F, found)            | (T, bal_zero ()) =>              (CONS (k, d, bal_plus1 (), left, p1), fixbal, found)            | (T, bal_plus1 ()) =>              let                val+ CONS (k1, d1, bal1, left1, right1) = p1              in                case+ bal1 of                | bal_plus1 () =>                  let                    val q = CONS (k, d, bal_zero (), left, left1)                    val q1 = CONS (k1, d1, bal_zero (), q, right1)                  in                    (q1, F, found)                  end                | _ =>                  let                    val p2 = left1                    val- CONS (k2, d2, bal2, left2, right2) = p2                    val q = CONS (k, d, minus_pos_bal bal2,                                  left, left2)                    val q1 = CONS (k1, d1, minus_neg_bal bal2,                                   right2, right1)                    val q2 = CONS (k2, d2, bal_zero (), q, q1)                  in                    (q2, F, found)                  end              end          end        | _ => (CONS (key, data, bal, left, right), F, T)  in    if avl_t_is_empty avl then      (CONS (key, data, bal_zero, NIL, NIL), F)    else      let        prval _ = lemma_avl_t_param avl        val (avl, _, found) = \$effmask_ntm search (avl, F, F)      in        (avl, found)      end  end fn {key_t : [email protected]} {data_t : [email protected]}avl_t_insert {size : int}             (avl  : avl_t (key_t, data_t, size),              key  : key_t,              data : data_t) :<>    [sz : pos] avl_t (key_t, data_t, sz) =  (avl_t_insert_or_replace<key_t><data_t> (avl, key, data)).0 fun {key_t : [email protected]} {data_t : [email protected]}push_all_the_way_left (stack : List (avl_t (key_t, data_t)),                       p     : avl_t (key_t, data_t)) :    List0 (avl_t (key_t, data_t)) =  let    prval _ = lemma_list_param stack  in    case+ p of    | NIL => stack    | CONS (_, _, _, left, _) =>      push_all_the_way_left (p :: stack, left)  end fun {key_t : [email protected]} {data_t : [email protected]}update_generator_stack (stack     : List (avl_t (key_t, data_t)),                        right     : avl_t (key_t, data_t)) :    List0 (avl_t (key_t, data_t)) =  let    prval _ = lemma_list_param stack  in    if avl_t_is_empty right then      stack    else      push_all_the_way_left<key_t><data_t> (stack, right)  end fn {key_t : [email protected]} {data_t : [email protected]}avl_t_make_data_generator {size : int}                          (avl  : avl_t (key_t, data_t, size)) :    () -<cloref1> Option data_t =  let    typedef avl_t = avl_t (key_t, data_t)     val stack = push_all_the_way_left<key_t><data_t> (LNIL, avl)    val stack_ref = ref stack     (* Cast stack_ref to its (otherwise untyped) pointer, so it can be       enclosed within ‘generate’. *)    val p_stack_ref = \$UNSAFE.castvwtp0{ptr} stack_ref     fun    generate () :<cloref1> Option data_t =      let        (* Restore the type information for stack_ref. *)        val stack_ref =          \$UNSAFE.castvwtp0{ref (List avl_t)} p_stack_ref         var stack : List0 avl_t = !stack_ref        var retval : Option data_t      in        begin          case+ stack of          | LNIL => retval := None ()          | p :: tail =>            let              val- CONS (_, d, _, left, right) = p            in              retval := Some d;              stack :=                update_generator_stack<key_t><data_t> (tail, right)            end        end;        !stack_ref := stack;        retval      end  in    generate  end (*------------------------------------------------------------------*)(* Hashmaps implemented with AVL trees and association lists.       *) (* The interface  - - - - - - - - - - - - - - - - - - - - - - - - - *) typedef hashmap_t (key_t  : [email protected]+,                   data_t : [email protected]+) =  avl_t (uint64, List1 @(key_t, data_t)) (* For simplicity, let us support only 64-bit hashes. *)extern fun {key_t : [email protected]}  (* Implement a hash function with this. *)hashmap_t\$hashfunc : key_t -<> uint64 extern fun {key_t : [email protected]}     (* Implement key equality with this. *)hashmap_t\$key_eq : (key_t, key_t) -<> bool extern funhashmap_t_nil :  {key_t : [email protected]} {data_t : [email protected]}  () -<> hashmap_t (key_t, data_t) extern fun {key_t  : [email protected]}           {data_t : [email protected]}hashmap_t_set (map  : hashmap_t (key_t, data_t),               key  : key_t,               data : data_t) :<>    hashmap_t (key_t, data_t) extern fun {key_t  : [email protected]}           {data_t : [email protected]}hashmap_t_get (map : hashmap_t (key_t, data_t),               key : key_t) :<>    Option data_t (*  Notes:    * Generators for hashmap_t produce their output in unspecified      order.    * Generators for keys and data values can be made by analogy to      the following generator for pairs, or can be written in terms      of the generator for pairs. (The former approach seems better;      it might copy less data.)*)extern fun {key_t  : [email protected]}           {data_t : [email protected]}hashmap_t_make_pairs_generator (map : hashmap_t (key_t, data_t)) :    () -<cloref1> Option @(key_t, data_t) (* The implementation - - - - - - - - - - - - - - - - - - - - - - - *) implementavl_t\$compare<uint64> (u, v) =  if u < v then    ~1  else if v < u then    1  else    0 implementhashmap_t_nil () =  avl_t_nil () fun {key_t  : [email protected]}    {data_t : [email protected]}remove_association {n : nat} .<n>.                   (lst : list (@(key_t, data_t), n),                    key : key_t) :<>    List0 @(key_t, data_t) =  (* This implementation uses linear stack space, and so presumes the     list is not extremely long. It preserves the order of the list,     although doing so is not necessary for persistence. (You might     wish to think about that, taking into account that the     order of traversal through a hashmap usually is considered     "unspecified".) *)  case+ lst of  | list_nil () => lst  | list_cons (head, tail) =>    if hashmap_t\$key_eq<key_t> (key, head.0) then      tail                      (* Assume there is only one match. *)    else      list_cons (head, remove_association (tail, key)) fun {key_t  : [email protected]}    {data_t : [email protected]}find_association {n : nat} .<n>.                 (lst : list (@(key_t, data_t), n),                  key : key_t) :<>    List0 @(key_t, data_t) =  (* This implementation is tail recursive. It will not build up the     stack. *)  case+ lst of  | list_nil () => lst  | list_cons (head, tail) =>    if hashmap_t\$key_eq<key_t> (key, head.0) then      lst    else      find_association (tail, key) implement {key_t} {data_t}hashmap_t_set (map, key, data) =  let    typedef lst_t = List1 @(key_t, data_t) (* Association list. *)    val hash = hashmap_t\$hashfunc<key_t> key    val lst_opt = avl_t_search_opt<uint64><lst_t> (map, hash)    val lst =      begin        case+ lst_opt of        | Some lst =>          (* There is already an association list for this hash value.             Remove any association already in it. *)          remove_association<key_t><data_t> (lst, key)        | None () =>          (* Start a new association list. *)          list_nil ()      end : List0 @(key_t, data_t)    val lst = list_cons (@(key, data), lst)  in    avl_t_insert<uint64><lst_t> (map, hash, lst)  end implement {key_t} {data_t}hashmap_t_get (map, key) =  let    typedef lst_t = List1 @(key_t, data_t) (* Association list. *)    val hash = hashmap_t\$hashfunc<key_t> key    val lst_opt = avl_t_search_opt<uint64><lst_t> (map, hash)  in    case+ lst_opt of    | None () => None{data_t} ()    | Some lst =>      begin        case+ find_association<key_t><data_t> (lst, key) of        | list_nil () => None{data_t} ()        | list_cons (@(_, data), _) => Some{data_t} data      end  end implement {key_t} {data_t}hashmap_t_make_pairs_generator (map) =  let    typedef pair_t = @(key_t, data_t)    typedef lst_t = List1 pair_t    typedef lst_t_0 = List0 pair_t     val avl_gen = avl_t_make_data_generator<uint64><lst_t> (map)     val current_alist_ref : ref lst_t_0 = ref (list_nil ())    val current_alist_ptr =      \$UNSAFE.castvwtp0{ptr} current_alist_ref  in    lam () =>      let        val current_alist_ref =          \$UNSAFE.castvwtp0{ref lst_t_0} current_alist_ptr      in        case+ !current_alist_ref of        | list_nil () =>          begin            case+ avl_gen () of            | None () => None ()            | Some lst =>              begin                case+ lst of                | list_cons (head, tail) =>                  begin                    !current_alist_ref := tail;                    Some head                  end              end          end        | list_cons (head, tail) =>          begin            !current_alist_ref := tail;            Some head          end      end  end (*------------------------------------------------------------------*) implementhashmap_t\$hashfunc<string> (s) =  string_hash s implementhashmap_t\$key_eq<string> (s, t) =  s = t typedef s2i_hashmap_t = hashmap_t (string, int) fns2i_hashmap_t_set (map  : s2i_hashmap_t,                   key  : string,                   data : int) :<> s2i_hashmap_t =  hashmap_t_set<string><int> (map, key, data) fns2i_hashmap_t_set_ref (map  : &s2i_hashmap_t >> _,                       key  : string,                       data : int) :<!wrt> void =  (* Update a reference to a persistent hashmap. *)  map := s2i_hashmap_t_set (map, key, data) fns2i_hashmap_t_get (map  : s2i_hashmap_t,                   key  : string) :<> Option int =  hashmap_t_get<string><int> (map, key) extern fun {}        (* {} = a template without template parameters *)s2i_hashmap_t_get_dflt\$dflt :<> () -> intfn {}                (* {} = a template without template parameters *)s2i_hashmap_t_get_dflt (map  : s2i_hashmap_t,                        key  : string) : int =  case+ s2i_hashmap_t_get (map, key) of  | Some x => x  | None () => s2i_hashmap_t_get_dflt\$dflt<> () overload [] with s2i_hashmap_t_set_refoverload [] with s2i_hashmap_t_get_dflt implementmain0 () =  let    implement s2i_hashmap_t_get_dflt\$dflt<> () = 0    var map = hashmap_t_nil ()    var gen : () -<cloref1> @(string, int)    var pair : Option @(string, int)  in    map["one"] := 1;    map["two"] := 2;    map["three"] := 3;    println! ("map[\"one\"] = ", map["one"]);    println! ("map[\"two\"] = ", map["two"]);    println! ("map[\"three\"] = ", map["three"]);    println! ("map[\"four\"] = ", map["four"]);    gen := hashmap_t_make_pairs_generator<string><int> map;    for (pair := gen (); option_is_some pair; pair := gen ())      println! (pair)  end (*------------------------------------------------------------------*)`
Output:
```\$ patscc -O2 -DATS_MEMALLOC_GCBDW hashmaps-postiats.dats -lxxhash -lgc && ./a.out
map["one"] = 1
map["two"] = 2
map["three"] = 3
map["four"] = 0
Some((two, 2))
Some((one, 1))
Some((three, 3))```

AutoHotkey

True arrays

AutoHotkey_L has Objects which function as associative arrays.

`associative_array := {key1: "value 1", "Key with spaces and non-alphanumeric characters !*+": 23}MsgBox % associative_array.key1	. "`n" associative_array["Key with spaces and non-alphanumeric characters !*+"]`

Legacy versions

AutoHotkey_Basic does not have typical arrays. However, variable names can be concatenated, simulating associative arrays.

`arrayX1 = firstarrayX2 = secondarrayX3 = fooarrayX4 = barLoop, 4  Msgbox % arrayX%A_Index%`

AutoIt

See here in the MSDN the reference for the Dictionary object that can be used in VBA. The following example shows how to create a dictionary, add/remove keys, change a key or a value, and check the existence of a key.

`; Associative arrays in AutoIt.; All the required functions are below the examples. ; Initialize an error handler to deal with any COM errors..global \$oMyError = ObjEvent("AutoIt.Error", "AAError") ; first example, simple.global \$simple ; Initialize your array ...AAInit(\$simple) AAAdd(\$simple, "Appple", "fruit")AAAdd(\$simple, "Dog", "animal")AAAdd(\$simple, "Silicon", "tetravalent metalloid semiconductor") ConsoleWrite("It is well-known that Silicon is a " & AAGetItem(\$simple, "Silicon") & "." & @CRLF)ConsoleWrite(@CRLF)  ; A more interesting example.. \$ini_path = "AA_Test.ini"; Put this prefs section in your ini file..; [test]; foo=foo value; foo2=foo2 value; bar=bar value; bar2=bar2 value  global \$associative_arrayAAInit(\$associative_array) ; We are going to convert this 2D array into a cute associative array where we; can access the values by simply using their respective key names..\$test_array = IniReadSection(\$ini_path, "test") for \$z = 1 to 2 ; do it twice, to show that the items are *really* there!	for \$i = 1 to \$test_array[0][0]		\$key_name = \$test_array[\$i][0]		ConsoleWrite("Adding '" & \$key_name & "'.." & @CRLF)		; key already exists in "\$associative_array", use the pre-determined value..		if AAExists(\$associative_array, \$key_name) then			\$this_value = AAGetItem(\$associative_array, \$key_name)			ConsoleWrite("key_name ALREADY EXISTS! : =>" & \$key_name & "<=" & @CRLF)		else			\$this_value = \$test_array[\$i][1]			; store left=right value pair in AA			if \$this_value then				AAAdd(\$associative_array, \$key_name, \$this_value)			endif		endif	nextnext ConsoleWrite(@CRLF & "Array Count: =>" & AACount(\$associative_array) & "<=" & @CRLF)AAList(\$associative_array) ConsoleWrite(@CRLF & "Removing 'foo'..")AARemove(\$associative_array, "foo") ConsoleWrite(@CRLF & "Array Count: =>" & AACount(\$associative_array) & "<=" & @CRLF)AAList(\$associative_array)  AAWipe(\$associative_array)  ; end   func AAInit(ByRef \$dict_obj)\$dict_obj = ObjCreate("Scripting.Dictionary")endfunc ; Adds a key and item pair to a Dictionary object..func AAAdd(ByRef \$dict_obj, \$key, \$val)    \$dict_obj.Add(\$key, \$val)    If @error Then return SetError(1, 1, -1)endfunc ; Removes a key and item pair from a Dictionary object..func AARemove(ByRef \$dict_obj, \$key)	\$dict_obj.Remove(\$key)	If @error Then return SetError(1, 1, -1)endfunc ; Returns true if a specified key exists in the associative array, false if not..func AAExists(ByRef \$dict_obj, \$key)	return \$dict_obj.Exists(\$key)endfunc ; Returns a value for a specified key name in the associative array..func AAGetItem(ByRef \$dict_obj, \$key)	return \$dict_obj.Item(\$key)endfunc ; Returns the total number of keys in the array..func AACount(ByRef \$dict_obj)	return \$dict_obj.Count endfunc ; List all the "Key" > "Item" pairs in the array..func AAList(ByRef \$dict_obj)ConsoleWrite("AAList: =>" & @CRLF)	local \$k = \$dict_obj.Keys ; Get the keys	; local \$a = \$dict_obj.Items ; Get the items (for reference)	for \$i = 0 to AACount(\$dict_obj) -1 ; Iterate the array		ConsoleWrite(\$k[\$i] & " ==> " & AAGetItem(\$dict_obj, \$k[\$i]) & @CRLF)	nextendfunc ; Wipe the array, obviously.func AAWipe(ByRef \$dict_obj)	\$dict_obj.RemoveAll()endfunc ; Oh oh!func AAError()	Local \$err = \$oMyError.number	If \$err = 0 Then \$err = -1	SetError(\$err)  ; to check for after this function returnsendfunc ;; End AA Functions. `

AWK

Arrays in AWK are indeed associative arrays.

`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}`

Babel

`     (("foo" 13)    ("bar" 42)    ("baz" 77)) ls2map !`

BaCon

`DECLARE associative ASSOC STRING associative("abc") = "first three"associative("xyz") = "last three" PRINT associative("xyz")`
Output:
```prompt\$ ./assoc
last three
```

String keys, with ASSOC to a given data type. Sizing is dynamic.

BASIC256

`global values\$, keys\$dim values\$[1]dim keys\$[1] call updateKey("a","apple")call updateKey("b","banana")call updateKey("c","cucumber") gosub show print "I like to eat a " + getValue\$("c") + " on my salad." call deleteKey("b")call updateKey("c","carrot")call updateKey("e","endive")gosub show end show:for t = 0 to countKeys()-1   print getKeyByIndex\$(t) + " " + getValueByIndex\$(t)next tprintreturn subroutine updateKey(key\$, value\$)   # update or add an item   i=findKey(key\$)   if i=-1 then      i = freeKey()      keys\$[i] = key\$   end if   values\$[i] = value\$end subroutine subroutine deleteKey(key\$)   # delete by clearing the key   i=findKey(key\$)   if i<>-1 then      keys\$[i] = ""   end ifend subroutine function freeKey()   # find index of a free element in the array   for n = 0 to keys\$[?]-1      if keys\$[n]="" then return n   next n   redim keys\$[n+1]   redim values\$[n+1]   return nend function function findKey(key\$)   # return index or -1 if not found   for n = 0 to keys\$[?]-1      if key\$=keys\$[n] then return n   next n   return -1end function function getValue\$(key\$)   # return a value by the key or "" if not existing   i=findKey(key\$)   if i=-1 then      return ""   end if   return values\$[i]end function function countKeys()   # return number of items   # remember to skip the empty keys (deleted ones)   k = 0   for n = 0 to keys\$[?] -1      if keys\$[n]<>"" then k++   next n   return kend function function getValueByIndex\$(i)   # get a value by the index   # remember to skip the empty keys (deleted ones)   k = 0   for n = 0 to keys\$[?] -1      if keys\$[n]<>"" then         if k=i then return values\$[k]         k++      endif   next n   return ""end function function getKeyByIndex\$(i)   # get a key by the index   # remember to skip the empty keys (deleted ones)   k = 0   for n = 0 to keys\$[?] -1      if keys\$[n]<>"" then         if k=i then return keys\$[k]         k++      endif   next n   return ""end function`
Output:
```a apple
b banana
c cucumber

I like to eat a cucumber on my salad.
a apple
e endive
c carrot```

Batch File

This is cheating, I'm sure of it.

`::assocarrays.cmd@echo offsetlocal ENABLEDELAYEDEXPANSIONset array.dog=1set array.cat=2set array.wolf=3set array.cow=4for %%i in (dog cat wolf cow) do call :showit array.%%i !array.%%i!set c=-27call :mkarray sicko flu 5 measles 6 mumps 7 bromodrosis 8for %%i in (flu measles mumps bromodrosis) do call :showit "sicko^&%%i" !sicko^&%%i!endlocalgoto :eof :mkarrayset %1^&%2=%3shift /2shift /2if "%2" neq "" goto :mkarraygoto :eof :showitecho %1 = %2goto :eof `
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```

BBC BASIC

`      REM Store some values with their keys:      PROCputdict(mydict\$, "FF0000", "red")      PROCputdict(mydict\$, "00FF00", "green")      PROCputdict(mydict\$, "0000FF", "blue")       REM Retrieve some values using their keys:      PRINT FNgetdict(mydict\$, "green")      PRINT FNgetdict(mydict\$, "red")      END       DEF PROCputdict(RETURN dict\$, value\$, key\$)      IF dict\$ = "" dict\$ = CHR\$(0)      dict\$ += key\$ + CHR\$(1) + value\$ + CHR\$(0)      ENDPROC       DEF FNgetdict(dict\$, key\$)      LOCAL I%, J%      I% = INSTR(dict\$, CHR\$(0) + key\$ + CHR\$(1))      IF I% = 0 THEN = "" ELSE I% += LEN(key\$) + 2      J% = INSTR(dict\$, CHR\$(0), I%)      = MID\$(dict\$, I%, J% - I%)`

Bracmat

The hash is the only built-in Bracmat class. It is best used for e.g. a large dictionary, when manipulation of a very long list of key/value pairs with pattern matching would become too CPU-intensive. The same key can be stored with different values, as the example shows. If that is not desirable, the key (and its value) should be removed first.

`  new\$hash:?myhash& (myhash..insert)\$(title."Some title")& (myhash..insert)\$(formula.a+b+x^7)& (myhash..insert)\$(fruit.apples oranges kiwis)& (myhash..insert)\$(meat.)& (myhash..insert)\$(fruit.melons bananas)& out\$(myhash..find)\$fruit& (myhash..remove)\$formula& (myhash..insert)\$(formula.x^2+y^2)& out\$(myhash..find)\$formula;`
Output:
```(fruit.melons bananas) (fruit.apples oranges kiwis)
formula.x^2+y^2```

Brat

`h = [:]  #Empty hash h[:a] = 1  #Assign valueh[:b] = [1 2 3] #Assign another value h2 = [a: 1, b: [1 2 3], 10 : "ten"]  #Initialized hash h2[:b][2]  #Returns 3`

C

Solution is at Associative arrays/Creation/C.

C#

Platform: .NET 1.x

`System.Collections.HashTable map = new System.Collections.HashTable();map["key1"] = "foo";`

Platform: .NET 2.0

`Dictionary<string, string> map = new Dictionary<string,string>();map[ "key1" ] = "foo";`
Works with: C# version 3.0+
`var map = new Dictionary<string, string> {{"key1", "foo"}};`

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.

`#include <map>`

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:

`std::map<A, B> exampleMap`

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

`std::map<int, double> exampleMap`

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.

`exampleMap[7] = 3.14`

Of course, you can use a variable (or any rvalue of the correct type) for the key or value parameters:

`int myKey = 7;double myValue = 3.14;exampleMap[myKey] = myValue;`

insert()

The second approach is a little more complicated. We have to use the pair<> template:

`exampleMap.insert(std::pair<int, double>(7,3.14));`

or by using make_pair to avoid repeating key/value types:

`exampleMap.insert(std::make_pair(7,3.14));`

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:

`myValue = exampleMap[myKey]`

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:

`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;}`

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.

`#include <map>#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;}`

Ceylon

`import ceylon.collection { 	ArrayList,	HashMap,	naturalOrderTreeMap} shared void run() { 	// the easiest way is to use the map function to create	// an immutable map	value myMap = map {		"foo" -> 5,		"bar" -> 10,		"baz" -> 15,		"foo" -> 6 // by default the first "foo" will remain	}; 	// or you can use the HashMap constructor to create	// a mutable one	value myOtherMap = HashMap {		"foo"->"bar"	};	myOtherMap.put("baz", "baxx"); 	// there's also a sorted red/black tree map	value myTreeMap = naturalOrderTreeMap {		1 -> "won",		2 -> "too",		4 -> "fore"	};	for(num->homophone in myTreeMap) {		print("``num`` is ``homophone``");	} }`

Chapel

In Chapel, associative arrays are regular arrays with a non-integer domain - values used as keys into the array. The creation of the domain is independent from the creation of the array, and in fact the same domain can be used for multiple arrays, creating associative arrays with identical sets of keys. When the domain is changed, all arrays that use it will be reallocated.

`// arr is an array of string to int. any type can be used in both places.var keys: domain(string);var arr: [keys] int; // keys can be added to a domain using +, new values will be initialized to the default value (0 for int)keys += "foo";keys += "bar";keys += "baz"; // array access via [] or ()arr["foo"] = 1;arr["bar"] = 4;arr("baz") = 6; // write auto-formats domains and arrayswriteln("Keys: ", keys);writeln("Values: ", arr); // keys can be deleted using -keys -= "bar"; writeln("Keys: ", keys);writeln("Values: ", arr); // chapel also supports array literalsvar arr2 = [ "John" => 3, "Pete" => 14 ]; writeln("arr2 keys: ", arr2.domain);writeln("arr2 values: ", arr2);`
Output:
```Keys: {foo, bar, baz}
Values: 1 4 6
Keys: {foo, baz}
Values: 1 6
arr2 keys: {John, Pete}
arr2 values: 3 14
```

Clojure

`{:key "value" :key2 "value2" :key3 "value3"}`

ColdFusion

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

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

Common 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.`

Component Pascal

BlackBox Componente Builder
Using a handmade collections module with the following interface

` DEFINITION Collections; 	IMPORT Boxes; 	CONST		notFound = -1; 	TYPE		Hash = POINTER TO RECORD 			cap-, size-: INTEGER;			(h: Hash) ContainsKey (k: Boxes.Object): BOOLEAN, NEW;			(h: Hash) Get (k: Boxes.Object): Boxes.Object, NEW;			(h: Hash) IsEmpty (): BOOLEAN, NEW;			(h: Hash) Put (k, v: Boxes.Object): Boxes.Object, NEW;			(h: Hash) Remove (k: Boxes.Object): Boxes.Object, NEW;			(h: Hash) Reset, NEW		END; 		HashMap = POINTER TO RECORD 			cap-, size-: INTEGER;			(hm: HashMap) ContainsKey (k: Boxes.Object): BOOLEAN, NEW;			(hm: HashMap) ContainsValue (v: Boxes.Object): BOOLEAN, NEW;			(hm: HashMap) Get (k: Boxes.Object): Boxes.Object, NEW;			(hm: HashMap) IsEmpty (): BOOLEAN, NEW;			(hm: HashMap) Keys (): POINTER TO ARRAY OF Boxes.Object, NEW;			(hm: HashMap) Put (k, v: Boxes.Object): Boxes.Object, NEW;			(hm: HashMap) Remove (k: Boxes.Object): Boxes.Object, NEW;			(hm: HashMap) Reset, NEW;			(hm: HashMap) Values (): POINTER TO ARRAY OF Boxes.Object, NEW		END; 		LinkedList = POINTER TO RECORD 			first-, last-: Node;			size-: INTEGER;			(ll: LinkedList) Add (item: Boxes.Object), NEW;			(ll: LinkedList) Append (item: Boxes.Object), NEW;			(ll: LinkedList) AsString (): POINTER TO ARRAY OF CHAR, NEW;			(ll: LinkedList) Contains (item: Boxes.Object): BOOLEAN, NEW;			(ll: LinkedList) Get (at: INTEGER): Boxes.Object, NEW;			(ll: LinkedList) IndexOf (item: Boxes.Object): INTEGER, NEW;			(ll: LinkedList) Insert (at: INTEGER; item: Boxes.Object), NEW;			(ll: LinkedList) IsEmpty (): BOOLEAN, NEW;			(ll: LinkedList) Remove (item: Boxes.Object), NEW;			(ll: LinkedList) RemoveAt (at: INTEGER), NEW;			(ll: LinkedList) Reset, NEW;			(ll: LinkedList) Set (at: INTEGER; item: Boxes.Object), NEW		END; 		Vector = POINTER TO RECORD 			size-, cap-: LONGINT;			(v: Vector) Add (item: Boxes.Object), NEW;			(v: Vector) AddAt (item: Boxes.Object; i: INTEGER), NEW;			(v: Vector) Contains (o: Boxes.Object): BOOLEAN, NEW;			(v: Vector) Get (i: LONGINT): Boxes.Object, NEW;			(v: Vector) IndexOf (o: Boxes.Object): LONGINT, NEW;			(v: Vector) Remove (o: Boxes.Object), NEW;			(v: Vector) RemoveIndex (i: LONGINT): Boxes.Object, NEW;			(v: Vector) Set (i: LONGINT; o: Boxes.Object): Boxes.Object, NEW;			(v: Vector) Trim, NEW		END; 	PROCEDURE NewHash (cap: INTEGER): Hash;	PROCEDURE NewHashMap (cap: INTEGER): HashMap;	PROCEDURE NewLinkedList (): LinkedList;	PROCEDURE NewVector (cap: INTEGER): Vector; END Collections. `

The program:

` MODULE BbtAssociativeArrays;IMPORT StdLog, Collections, Boxes; PROCEDURE Do*;VAR	hm : Collections.HashMap;	o : Boxes.Object;	keys, values: POINTER TO ARRAY OF Boxes.Object;	i: INTEGER; BEGIN	hm := Collections.NewHashMap(1009);	o := hm.Put(Boxes.NewString("first"),Boxes.NewInteger(1));	o := hm.Put(Boxes.NewString("second"),Boxes.NewInteger(2));	o := hm.Put(Boxes.NewString("third"),Boxes.NewInteger(3));	o := hm.Put(Boxes.NewString("one"),Boxes.NewInteger(1)); 	StdLog.String("size: ");StdLog.Int(hm.size);StdLog.Ln; END Do; END BbtAssociativeArrays. `

Execute:^Q BbtAssociativeArrays.Do

Output:
```size:  4
```

Crystal

`hash1 = {"foo" => "bar"} # hash literals that don't perfectly match the intended hash type must be given an explicit type specification# the following would fail without `of String => String|Int32`hash2 : Hash(String, String|Int32) = {"foo" => "bar"} of String => String|Int32`

D

`void main() {    auto hash = ["foo":42, "bar":100];    assert("foo" in hash);}`

Dao

`m = { => } # empty ordered map, future inserted keys will be orderedh = { -> } # empty hash map, future inserted keys will not be ordered m = { 'foo' => 42, 'bar' => 100 } # with ordered keysh = { 'foo' -> 42, 'bar' -> 100 } # with unordered keys`

Dart

` main() {	var rosettaCode = { // Type is inferred to be Map<String, String>		'task': 'Associative Array Creation'	}; 	rosettaCode['language'] = 'Dart'; 	// The update function can be used to update a key using a callback	rosettaCode.update( 'is fun',  // Key to update		(value) => "i don't know", // New value to use if key is present		ifAbsent: () => 'yes!' // Value to use if key is absent	); 	assert( rosettaCode.toString() == '{task: Associative Array Creation, language: Dart, is fun: yes!}'); 	// If we type the Map with dynamic keys and values, it is like a JavaScript object	Map<dynamic, dynamic> jsObject = {		'key': 'value',		1: 2,		1.5: [ 'more', 'stuff' ],		#doStuff: () => print('doing stuff!') // #doStuff is a symbol, only one instance of this exists in the program. Would be :doStuff in Ruby	}; 	print( jsObject['key'] );	print( jsObject[1] ); 	for ( var value in jsObject[1.5] )		print('item: \$value'); 	jsObject[ #doStuff ](); // Calling the function 	print('\nKey types:');	jsObject.keys.forEach( (key) => print( key.runtimeType ) );}  `
Output:
```value
2
item: more
item: stuff
doing stuff!

Key types:
String
int
double
Symbol
```

Delphi

`program AssociativeArrayCreation; {\$APPTYPE CONSOLE} uses Generics.Collections; var  lDictionary: TDictionary<string, Integer>;begin  lDictionary := TDictionary<string, Integer>.Create;  try    lDictionary.Add('foo', 5);    lDictionary.Add('bar', 10);    lDictionary.Add('baz', 15);    lDictionary.AddOrSetValue('foo', 6); // replaces value if it exists  finally    lDictionary.Free;  end;end.`

Diego

Diego has in-built `hash` and `dict` (short for 'dictionary') objects which function as associative arrays. The only exception is that `hash` can only accept uuid datatypes for keys. Diego also has `hash_` verb and `_hash` posit, used to hash an object/command.

To create a dictionary associative array:

`use_namespace(rosettacode)_me();     add_dict(tanzanianBanknoteObverseDipiction)_keys(500,1000,2000,5000,10000)_values(Karume,Nyerere,lion,black rhinoceros,elephant); reset_ns[];`

To create a hash associative array:

`use_namespace(rosettacode)_me();     add_hash(tanzanianBanknoteReverseDipiction)_values(        University of Dar es Salaam\, Central Hall Building,        Ikulu\, Dar es Salaam,        Ngome Kongwe\, Zanzibar,        Geita Cyanid Leaching Plant,        Bank of Tanzania Headquarters\, Dar es Salaam    ); reset_ns[];`

Dyalect

Dyalect has a `Tuple` data type which allows to add labels to values:

`var t = (x: 1, y: 2, z: 3)print(t.Keys().ToArray())`
Output:
`[x, y, z]`

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)`

EchoLisp

` (lib 'hash) ;; needs hash.lib(define H (make-hash)) ;; new hash table;; keys may be symbols, numbers, strings ..;; values may be any lisp object(hash-set H 'simon 'antoniette)   → antoniette(hash-set H 'antoinette 'albert)   → albert(hash-set H "Elvis" 42)    → 42(hash-ref H 'Elvis)    → #f ;; not found. Elvis is not "Elvis"(hash-ref H "Elvis")    → 42(hash-ref H 'simon)    → antoniette(hash-count H)    → 3 `

Elena

ELENA 5.0:

`import system'collections; public program(){    // 1. Create    var map := Dictionary.new();    map["key"] := "foox";    map["key"] := "foo";    map["key2"]:= "foo2";    map["key3"]:= "foo3";    map["key4"]:= "foo4";}`

Strong typed dictionary

`import system'collections; public program(){    // 1. Create    auto map := new Map<string,string>();    map["key"] := "foox";    map["key"] := "foo";    map["key2"]:= "foo2";    map["key3"]:= "foo3";    map["key4"]:= "foo4";}`

Elixir

Translation of: Erlang
`defmodule RC do  def test_create do    IO.puts "< create Map.new >"    m = Map.new                   #=> creates an empty Map    m1 = Map.put(m,:foo,1)    m2 = Map.put(m1,:bar,2)    print_vals(m2)    print_vals(%{m2 | foo: 3})  end   defp print_vals(m) do    IO.inspect m    Enum.each(m, fn {k,v} -> IO.puts "#{inspect k} => #{v}" end)  endend RC.test_create`
Output:
```< create Map.new >
%{bar: 2, foo: 1}
:bar => 2
:foo => 1
%{bar: 2, foo: 3}
:bar => 2
:foo => 3
```

Emacs Lisp

`(setq my-table (make-hash-table))(puthash 'key 'value my-table)`

`make-hash-table` compares keys with `eql` by default. This suits symbols and numbers (including floating point). For string keys an `equal` test can be used,

`(setq my-table (make-hash-table :test 'equal))(puthash "key" 123 my-table)`

`define-hash-table-test` can create other key comparison types.

Erlang

Erlang offers several associative array type data structures, this example uses the dictionary data structure.

` -module(assoc).-compile([export_all]). test_create() ->       D = dict:new(),    D1 = dict:store(foo,1,D),    D2 = dict:store(bar,2,D1),    print_vals(D2),    print_vals(dict:store(foo,3,D2)). print_vals(D) ->    lists:foreach(fun (K) ->                          io:format("~p: ~b~n",[K,dict:fetch(K,D)])                  end, dict:fetch_keys(D)). `
Output:
```32> assoc:test_create().
bar: 2
foo: 1
bar: 2
foo: 3
ok
```

F#

.NET 3.5 Generic Dictionary (mutable)

` let dic = System.Collections.Generic.Dictionary<string,string>() ;;dic.Add("key","val") ;dic.["key"] <- "new val" ; `

Functional dictionary (immutable)

` let d = [("key","val");("other key","other val")] |> Map.ofListlet 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"   `

Factor

Associative mappings follow the associative protocol. See the docs. Here's an example using a hashtable that can be run in the listener :

`H{ { "one" 1 } { "two" 2 } }{ [ "one" swap at . ]  [ 2 swap value-at . ]  [ "three" swap at . ]  [ [ 3 "three" ] dip set-at ]  [ "three" swap at . ] } cleave`

Fantom

Associative arrays are called 'maps' in 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     }   }} `

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.

`: get ( key len table -- data )     \ 0 if not present  search-wordlist if    >body @  else 0 then ; : put ( data key len table -- )  >r 2dup [email protected] 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 bar5 s" alpha" bar put9 s" beta"  bar put2 s" gamma" bar puts" alpha" bar get .    \ 58 s" Alpha" bar put    \ Forth dictionaries are normally case-insensitives" alpha" bar get .   \ 8`

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

`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-insert10 s" bar" htable hct-insert15 s" baz" htable hct-insert \ Get entry from the table s" bar" htable hct-get [IF]  .( Value:) . cr[ELSE]  .( Entry not present.) cr[THEN]`

FreeBASIC

Uses unions to store the keys and associated values, and FreeBASIC's ability to resize arrays makes adding new entries easy.

`#define max(a, b) Iif(a>b,a,b) enum datatype    'for this demonstration we'll allow these five data types    BOOL    STRNG    BYYTE    INTEG    FLOATend enum union value    bool as boolean    strng as string*32    byyte as byte    integ as integer    float as doubleend union type dicitem    'one part of the dictionary entry, either the key or the value    datatype as datatype   'need to keep track of what kind of data it is    value as valueend type type dicentry    'a dic entry has two things, a key and a value    key as dicitem    value as dicitemend type sub add_dicentry( Dic() as dicentry, entry as dicentry )    redim preserve Dic(0 to max(ubound(Dic)+1,0))    Dic(ubound(Dic)) = entry    returnend sub redim as dicentry Dictionary(-1)  'initialise a dictionary with no entries as yet dim as dicentry thing1, thing2 'generate some test dictionary entrieswith thing1    with .key        .datatype = STRNG        .value.strng = "Cat"    end with    with .value        .datatype = STRNG        .value.strng = "Mittens"    end withend with with thing2    with .key        .datatype = integ        .value.integ = 32767    end with    with .value        .datatype = float        .value.float = 2.718281828    end withend with add_dicentry( Dictionary(), thing1 )add_dicentry( Dictionary(), thing2 ) print Dictionary(0).value.value.strngprint Dictionary(1).key.value.integ`
Output:
```Mittens
32767
```

Free Pascal

FPC 3.2.0.+. Similar to Delphi.

`program AssociativeArrayCreation;{\$IFDEF FPC}{\$MODE DELPHI}{\$ENDIF} {\$IFDEF WINDOWS}{\$APPTYPE CONSOLE}{\$ENDIF}uses Generics.Collections; var  lDictionary: TDictionary<string, Integer>;begin  lDictionary := TDictionary<string, Integer>.Create;  try    lDictionary.Add('foo', 5);    lDictionary.Add('bar', 10);    lDictionary.Add('baz', 15);    lDictionary.AddOrSetValue('foo', 6); // replaces value if it exists  finally    lDictionary.Free;  end;end.`

FPC 2.4+. Using FGL instead of rtl-generics:

`program AssociativeArrayCreation;{\$IFDEF WINDOWS}{\$APPTYPE CONSOLE}{\$ENDIF}{\$MODE DELPHI} uses fgl; var  lDictionary: TFPGMap<string, Integer>;begin  lDictionary := TFPGMap<string, Integer>.Create;  try    lDictionary.Add('foo', 5);    lDictionary.Add('bar', 10);    lDictionary.Add('baz', 15);  finally    lDictionary.Free;  end;end.`

Futhark

`let associative_array = {key1=1,key2=2}`

Go

Allowable key types are those with == and != operators. This includes is boolean, numeric, string, pointer, channel, and interface types. It also includes structs and arrays containing only these types. Disallowed as map keys are all slice, function, and map types.

`// declare a nil map variable, for maps from string to intvar x map[string]int // make an empty mapx = make(map[string]int) // make an empty map with an initial capacityx = make(map[string]int, 42) // set a valuex["foo"] = 3 // getting valuesy1 := x["bar"]     // zero value returned if no map entry exists for the keyy2, ok := x["bar"] // ok is a boolean, true if key exists in the map // removing keysdelete(x, "foo") // make a map with a literalx = map[string]int{	"foo": 2, "bar": 42, "baz": -1,}`

Gosu

As an OOP language with generics Gosu can use any variety of Map classes. In addition Gosu provides associative array syntax for all objects.

`// empty mapvar emptyMap = new HashMap<String, Integer>() // map initializationvar map = {"Scott"->50, "Carson"->40, "Luca"->30, "Kyle"->38} // map key/value assignmentmap["Scott"] = 51 // get a valuevar x = map["Scott"] // remove an entrymap.remove("Scott") // loop and mapsfor(entry in map.entrySet()) {  print("Key: \${entry.Key}, Value: \${entry.Value}") } // functional iterationmap.eachKey(\ k ->print(map[k]))map.eachValue(\ v ->print(v))map.eachKeyAndValue(\ k, v -> print("Key: \${v}, Value: \${v}"))var filtered = map.filterByValues(\ v ->v < 50) // any object can be treated as an associative arrayclass Person {  var name: String  var age: int }// access properties on Person dynamically via associative array syntaxvar scott = new Person()scott["name"] = "Scott"scott["age"] = 29`

Groovy

Create an empty map and add values

`map = [:]map[7] = 7map['foo'] = 'foovalue'map.put('bar', 'barvalue')map.moo = 'moovalue' assert 7 == map[7]assert 'foovalue' == map.fooassert 'barvalue' == map['bar']assert 'moovalue' == map.get('moo')`

Create a pre-populated map and verify values

`map = [7:7, foo:'foovalue', bar:'barvalue', moo:'moovalue'] assert 7 == map[7]assert 'foovalue' == map.fooassert 'barvalue' == map['bar']assert 'moovalue' == map.get('moo')`

Harbour

Create an empty array and add values:

`arr := { => }arr[ 10 ] := "Val_10"arr[ "foo" ] := "foovalue"`

Create and initialize array:

`arr := hb_Hash( 10, "Val_10", "foo", "foovalue" )// orarr := { 10 => "Val_10", "foo" => "foovalue" }`

Binary trees:

Works with: GHC
`import Data.Map dict = fromList [("key1","val1"), ("key2","val2")] ans = Data.Map.lookup "key2" dict  -- evaluates to Just "val2" `

It is also possible to use association lists (lists of pairs). It is inefficient (O(n) lookup), but simple.

`dict = [("key1","val1"), ("key2","val2")] ans = lookup "key2" dict  -- evaluates to Just "val2" `

GHC also had an imperative hash table implementation in the `Data.HashTable` module, but was removed in `GHC 7.8`.

Other standard associatives arrays libraries are : `Data.IntMap` and `Data.HasMap`

hexiscript

`let d         dict 2  # Initial estimated sizelet d["test"] "test"  # Strings can be used as indexlet d[123]    123     # Integers can also be used as index println d["test"]println d[123]`

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.

`procedure main()    local t   t := table()    t["foo"] := "bar"   write(t["foo"])end`

Inform 7

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

Static relation

`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.`

Dynamic relation

`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.`

Ioke

`{a: "a", b: "b"}`

J

Usually, in J, you would use a named pair of (same length) lists for this purpose - one of keys, one of values. There are a number of details here that vary with the the intended use patterns. (First you get it working and then if you run into bottlenecks you rebuild things to relieve the problems).

However, it's also possible to use the symbol table itself to hold the names. The symbol table has limitations (can only accept syntactically valid names), but we can turn arbitrary strings into valid symbols using base 62 encode and prefixing with a letter (hypothetically speaking, base 64 encode would let us build longer names than base 62, because of computational complexity issues - but the J symbol table also comes with a name length limit - 255 characters - and does not support 64 different characters in names):

`coclass 'assocArray'    encode=: 'z', (a.{~;48 65 97(+ i.)&.>10 26 26) {~ 62x #.inv 256x #. a.&i.    get=: "[email protected]    has=: 0 <: [email protected]<@encode    set=:4 :'(encode x)=:y'`

Example use:

`   example=: conew 'assocArray'   'foo' set__example 1 2 31 2 3   'bar' set__example 4 5 64 5 6   get__example 'foo'1 2 3   has__example 'foo'1   bletch__example=: 7 8 9   get__example 'bletch'7 8 9   codestroy__example''`

Note that J's symbols (http://www.jsoftware.com/help/dictionary/dsco.htm) might also be used for this purpose. However, symbols are not garbage collected within a J session (and, instead, a mechanism is provided to optionally preserve them across sessions).

Java

Works with: Java version 1.5+

Defining the Map:

`Map<String, Integer> map = new HashMap<String, Integer>();map.put("foo", 5);map.put("bar", 10);map.put("baz", 15);map.put("foo", 6);`

"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:

`public static Map<String, Integer> map = new HashMap<String, Integer>(){{   put("foo", 5);   put("bar", 10);   put("baz", 15);   put("foo", 6);}};`

Retrieving a value:

`map.get("foo"); // => 6map.get("invalid"); // => null`

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:

`for (String key: map.keySet())    System.out.println(key);`

Iterate over values:

`for (int value: map.values())   System.out.println(value);`

Iterate over key, value pairs:

`for (Map.Entry<String, Integer> entry: map.entrySet())   System.out.println(entry.getKey() + " => " + entry.getValue());`

JavaScript

ECMAScript5.1 does not have associative arrays, however Objects (which are just an unordered bundle of name/value pairs) can be used like associative arrays. JavaScript Arrays may also be used, but Objects are the convention.

Javascript object property names (keys) are strings. Other types and expressions can be used with square bracket notation, they are evaluated and converted to strings and the result used as the property name. Using quotes on property names avoids potential collisions with reserved JavaScript key words.

`var assoc = {}; assoc['foo'] = 'bar';assoc['another-key'] = 3; // dot notation can be used if the property name is a valid identifierassoc.thirdKey = 'we can also do this!';assoc[2] = "the index here is the string '2'"; //using JavaScript's object literal notationvar assoc = {  foo: 'bar',  'another-key': 3 //the key can either be enclosed by quotes or not}; //iterating keysfor (var key in assoc) {  // hasOwnProperty() method ensures the property isn't inherited  if (assoc.hasOwnProperty(key)) {    alert('key:"' + key + '", value:"' + assoc[key] + '"');  }}`

ECMAScript 6 (ES6) offers both a map and a weak map implementation. While Objects must use strings, Maps may use objects, functions, and numbers as keys in addition to strings.

`var map = new Map(),    fn = function () {},    obj = {}; map.set(fn, 123);map.set(obj, 'abc');map.set('key', 'val');map.set(3, x => x + x); map.get(fn); //=> 123map.get(function () {}); //=> undefined because not the same functionmap.get(obj); //=> 'abc'map.get({}); //=> undefined because not the same objectmap.get('key'); //=> 'val'map.get(3); //=> (x => x + x) map.size; //=> 4 //iterating using ES6 for..of syntaxfor (var key of map.keys()) {  console.log(key + ' => ' + map.get(key));}`

jq

Associative Arrays with String-Valued Keys

In jq, JSON objects can be used as associative arrays, it being understood that only strings can be used as keys. To avoid confusion, for the remainder of this section, we refer to JSON objects as such. Their type in jq is "object".

`# An empty object:{} # Its type:{} | type# "object" # An object literal:{"a": 97, "b" : 98} # Programmatic object construction:reduce ("a", "b", "c", "d") as \$c ({}; . +  { (\$c) : (\$c|explode[.0])} )# {"a":97,"c":99,"b":98,"d":100} # Same as above:reduce range (97;101) as \$i ({}; . + { ([\$i]|implode) : \$i }) # Addition of a key/value pair by assignment:{}["A"] = 65  # in this case, the object being added to is {} # Alteration of the value of an existing key:{"A": 65}["A"] = "AA"`

Associative Arrays with JSON-Valued Keys

In this subsection, we define addKey(key;value), getKey(key), and removeKey(key) to operate on a hash table for which the keys may be any JSON entities. This is done by defining a collisionless hash function.

`def collisionless:   if type == "object" then with_entries(.value = (.value|collisionless))|tostring   elif type == "array" then map(collisionless)|tostring   else (type[0:1] + tostring)   end; # WARNING: addKey(key;value) will erase any previous value associated with keydef addKey(key;value):  if type == "object" then  . + { (key|collisionless): value }  else {} | addKey(key;value)  end; def getKey(key): .[key|collisionless]; def removeKey(key): delpaths( [ [key|collisionless] ] );`

Example:

`{} | addKey(1;"one") | addKey(2; "two") | removeKey(1) | getKey(2)`

produces:

`"two"`

Jsish

From Javascript. jsish warns of duplicate var, in this case the assoc variable is reused.

`var assoc = {}; assoc['foo'] = 'bar';assoc['another-key'] = 3; // dot notation can be used if the property name is a valid identifierassoc.thirdKey = 'we can also do this!';assoc[2] = "the index here is the string '2'";;assoc; //using JavaScript's object literal notationvar assoc = {  foo: 'bar',  'another-key': 3 //the key can either be enclosed by quotes or not}; //iterating keysfor (var key in assoc) {  // hasOwnProperty() method ensures the property isn't inherited  if (assoc.hasOwnProperty(key)) {    puts('key:"' + key + '", value:"' + assoc[key] + '"');  }};assoc; /*=!EXPECTSTART!=associativeArray.jsi:12: warn: duplicate var: assocassoc ==> { 2:"the index here is the string \'2\'", "another-key":3, foo:"bar", thirdKey:"we can also do this!" }key:"another-key", value:"3"key:"foo", value:"bar"assoc ==> { "another-key":3, foo:"bar" }=!EXPECTEND!=*/`
Output:
```prompt\$ jsish -u associativeArray.jsi
[PASS] associativeArray.jsi```

Julia

Works with: Julia version 0.6

We build dictionaries associating to some characters their code points, by listing the key/value pairs, through a dictionary comprehension, by creating an empty dictionary and filling it, by using the specific syntax associated to typed dictionaries.

`dict = Dict('a' => 97, 'b' => 98) # list keys/values# Dict{Char,Int64} with 2 entries:#   'b' => 98#   'a' => 97 dict = Dict(c => Int(c) for c = 'a':'d') # dict comprehension# Dict{Char,Int64} with 4 entries:#   'b' => 98#   'a' => 97#   'd' => 100#   'c' => 99 dict['é'] = 233; dict # add an element# Dict{Char,Int64} with 3 entries:#   'b' => 98#   'a' => 97#   'é' => 233 emptydict = Dict() # create an empty dict# Dict{Any,Any} with 0 entries dict["a"] = 1 # type mismatch# ERROR: MethodError: Cannot `convert` an object of type String to an object of type Char typeof(dict) # type is infered correctly# Dict{Char,Int64} `

K

Keys in a dictionary must be symbols (`symbol).

`   / creating an dictionary   d1:.((`foo;1); (`bar;2); (`baz;3))    / extracting a value   d1[`bar]2`

Another approach.

`   d2: .()          / create empty dictionary   d2[`"zero"]:0   d2[`"one"]:1   d2[`"two"]:2    d2.((`zero;0;)  (`one;1;)  (`two;2;))`

Extracting the keys and values.

`   !d2              / the keys`zero `one `two    d2[]             /  the values0 1 2`

Kotlin

Translation of: Java
`fun main(args: Array<String>) {    // map definition:    val map = mapOf("foo" to 5,                    "bar" to 10,                    "baz" to 15,                    "foo" to 6)     // retrieval:    println(map["foo"]) // => 6    println(map["invalid"]) // => null     // check keys:    println("foo" in map) // => true    println("invalid" in map) // => false     // iterate over keys:    for (k in map.keys) print("\$k ")    println()     // iterate over values:    for (v in map.values) print("\$v ")    println()     // iterate over key, value pairs:    for ((k, v) in map) println("\$k => \$v")}`

Lambdatalk

Associative arrays are not currently built in the JS.js kernel of lambdatalk but are added via the lib_hash library page.

`  1) a (currently) reduced set of functions: HASH: [5] [H.lib, H.new, H.disp, H.get, H.set!] 2) building an associative array: {def H key value | ...} {def capitals {H.new nyk New York, United States |         lon London, United Kingdom |        par Paris, France |        mos Moscou, Russia }}-> capitals 3) displaying: {H.disp hash}{H.disp {capitals}}    -> [nyk: New York, United Stateslon: London, United Kingdompar: Paris, Francemos: Moscou, Russia] 4) getting a value from a key: {H.get hash key} {H.get {capitals} nyk} -> New York, United States{H.get {capitals} lon} -> London, United Kingdom{H.get {capitals} par} -> Paris, France{H.get {capitals} mos} -> Moscou, Russia 5) adding a new (key,value): {H.set! hash key value} {H.disp {H.set! {capitals} bar Barcelona, Catalunya}}-> [nyk: New York, United Stateslon: London, United Kingdompar: Paris, Francemos: Moscou, Russiabar: Barcelona, Catalunya] 6) editing a key {H.disp   {H.set! {capitals}          nyk           {H.get {capitals} nyk} of America}} // adding "of America" to nyk-> [nyk: New York, United States of Americalon: London, United Kingdompar: Paris, Francemos: Moscou, Russiabar: Barcelona, Catalunya] `

Lang5

`: dip  swap '_ set execute _ ; : nip  swap drop ;: first  0 extract nip ; : second  1 extract nip ; : assoc-in  swap keys eq ;: assoc-index'  over keys swap eq [1] index collapse ;: at  swap assoc-index' subscript collapse second ;: delete-at  swap assoc-index' first remove ;: keys  1 transpose first ;: set-at    over 'dup dip assoc-in '+ reduce if 'dup dip delete-at then    "swap 2 compress 1 compress" dip swap append ; [['foo 5]]10 'bar rot set-at'bar over at .'hello 'bar rot set-at20 'baz rot set-at .`

langur

Hash keys in langur may be numbers or strings. Number keys are simplified, so that 1.0 is the same key as 1.

`var .hash = h{1: "abc", "1": 789} # may assign with existing or non-existing hash key (if hash is mutable).hash[7] = 49 writeln .hash[1]writeln .hash[7]writeln .hash["1"] # using an alternate value in case of invalid index; prevents exceptionwriteln .hash[1; 42]writeln .hash[2; 42]`
Output:
```abc
49
789
abc
42```

Lasso

`// In Lasso associative arrays are called maps // Define an empty maplocal(mymap = map) // Define a map with contentlocal(mymap = map(	'one'	= 'Monday',	'2'	= 'Tuesday',	3	= 'Wednesday')) // add elements to an existing map#mymap -> insert('fourth' = 'Thursday') // retrieve a value from a map#mymap -> find('2') // Tuesday'<br />'#mymap -> find(3) // Wednesday, found by the key not the position'<br />' // Get all keys from a map#mymap -> keys // staticarray(2, fourth, one, 3)'<br />' // Iterate thru a map and get valueswith v in #mymap do {^	#v	'<br />'^}// Tuesday<br />Thursday<br />Monday<br />Wednesday<br /> // Perform actions on each value of a map#mymap -> foreach => {	#1 -> uppercase	#1 -> reverse}#mymap // map(2 = YADSEUT, fourth = YADSRUHT, one = YADNOM, 3 = YADSENDEW)`

LFE

` (let* ((my-dict (: dict new))       (my-dict (: dict store 'key-1 '"value 1" my-dict))       (my-dict (: dict store 'key-2 '"value 2" my-dict)))  (: io format '"size: ~p~n" (list (: dict size my-dict)))  (: io format '"some data: ~p~n" (list (: dict fetch 'key-1 my-dict))))  `

Liberty BASIC

Needs the sublist library from http://basic.wikispaces.com/SubList+Library since LB does not have built-in associative arrays.

` data "red",      "255 50 50",       "green", "50 255 50",     "blue", "50 50 255"data "my fave",  "220 120 120",     "black", "0 0 0" myAssocList\$ ="" for i =1 to 5    read k\$    read dat\$    call sl.Set myAssocList\$, k\$, dat\$next i print " Key 'green' is associated with data item "; sl.Get\$( myAssocList\$, "green") `
```Key 'green' is associated with data item 50 255 50
```

Lingo

`props = [#key1: "value1", #key2: "value2"] put props[#key2]-- "value2"put props["key2"]-- "value2"put props.key2-- "value2"put props.getProp(#key2)-- "value2"`

LiveCode

Livecode arrays are only associative, but can be accessed by ordinal if they are used as the key.

`command assocArray    local tArray    put "value 1" into tArray["key 1"]    put 123 into tArray["key numbers"]    put "a,b,c" into tArray["abc"]     put "number of elements:" && the number of elements of tArray & return & \          "length of item 3:" && the length of tArray["abc"] & return & \          "keys:" && the keys of tArrayend assocArray`

Output

`number of elements: 3length of item 3: 5keys: key numbersabckey 1`

Logo

UCB Logo has "property lists" which associate names with values. They have their own namespace.

`pprop "animals "cat 5pprop "animals "dog 4pprop "animals "mouse 11print gprop "animals "cat    ; 5remprop "animals "dogshow plist "animals    ;  [mouse 11 cat 5]`

LOLCODE

BUKKITs are associative arrays

`HAI 1.2I HAS A Hash ITZ A BUKKITHash HAS A key1 ITZ "val1" BTW This works for identifier-like keys, like obj.key in JavaScriptHash HAS A SRS "key-2" ITZ 1 BTW Non-identifier keys need the SRSVISIBLE Hash'Z SRS "key-2"KTHXBYE `
Output:
`1`

Lua

Lua tables are Hashes

`hash = {}hash[ "key-1" ] = "val1"hash[ "key-2" ] = 1hash[ "key-3" ] = {}`

Returns nil on unknown key.

M2000 Interpreter

Μ2000 has Inventory object to use it as a Map. All keys converted to strings. If a key has no value then key is the value until we place one. A special type of Inventory is the Inventory Queue, where we can use same keys, and we can't delete except from the last append.

` Inventory A="100":=1, "200":=5, 10:=500,  20:="Hello There"Print len(A)Print A(100)=1, A(200)=5, A\$(20)="Hello There"Return A, 100:=3, 200:=7\\ print all elementsPrint AFor i=0 to Len(A)-1 {      \\ Key, Value by current order (using !)      Print Eval\$(A, i), A\$(i!)}\\ IteratorAppend A, "End":=5000N=Each(A)While N {      Print Eval\$(A, N^), A\$(N^!)}Print Len(A)=5Delete A, "100", 10, 20Print Len(A)=2If Exist(A, "End") Then Print Eval(A)=5000  `

Maple

Maple tables are hashed arrays. A table can be constructed by using the table constructor.

`> T := table( [ (2,3) = 4, "foo" = 1, sin(x) = cos(x) ] );          T := table(["foo" = 1, sin(x) = cos(x), (2, 3) = 4]) > T[2,3];                                   4 > T[sin(x)];                                 cos(x) > T["foo"];                                   1`

New entries are added by assignment.

`> T[ "bar" ] := 2;                             T["bar"] := 2 > T[ "bar" ];                                        2`

Entries can be removed as follows.

`> T[ "foo" ] := evaln( T[ "foo" ] );                          T["foo"] := T["foo"] > T[ "foo" ];                                T["foo"]`

(The latter output indicates that T["foo"] is an unassigned name.)

Mathematica / Wolfram Language

`a[2] = "string"; a["sometext"] = 23;`

MATLAB / Octave

MATLAB/Octave: structs

Associative arrays are called structs. The following methods of creating hash are equivalent.

`   hash.a = 1;   hash.b = 2;   hash.C = [3,4,5];   `

alternatively

`   hash = [];    hash = setfield(hash,'a',1); 	   hash = setfield(hash,'b',2); 	   hash = setfield(hash,'C',[3,4,5]);  `

or

`   hash.('a') = 1; 	   hash.('b') = 2; 	   hash.('C') = [3,4,5];   `
```>>    disp(hash)
scalar structure containing the fields:
a =  1
b =  2
C =

3   4   5```

Limitation: key must be a string containing only characters, digits and underscores, and the key string must start with a character.

MATLAB only: containers.Map

Use of containers.Map removes some restrictions on key types that structs have. Keys can all be numeric or all be strings. Values can be of any type. Key and value types cannot be changed after creation of the containers.Map object.

`m = containers.Map({'a' 'b' 'C'}, [1 2 3]);`

is equivalent to

`m = containers.Map;m('a') = 1;m('b') = 2;m('C') = 3;`

since the KeyType defaults to 'char'. For numeric keys, the key and value types must be specified at creation.

`m = containers.Map([51 72 37], {'fiftyone' 'seventytwo' 'thirtyseven'});`

is equivalent to

`m = containers.Map('KeyType', 'double', 'ValueType', 'any');m(51) = 'fiftyone';m(72) = 'seventytwo';m(37) = 'thirtyseven';`

Usage:

```>> m = containers.Map([51 72 37], {'fiftyone' 'seventytwo' 'thirtyseven'});
>> keys(m)

ans =

[37]    [51]    [72]

>> values(m)

ans =

'thirtyseven'    'fiftyone'    'seventytwo'```

Maxima

`/* No need to declare anything, undeclared arrays are hashed */ h[1]: 6;h[9]: 2; arrayinfo(h);[hashed, 1, [1], [9]]`

min

Works with: min version 0.19.6
`{1 :one 2 :two 3 :three}`

MiniScript

A map literal in MiniScript is enclosed in curly braces, with key:value pairs separated by commas. Keys and values may be any type. Retrieval or assignment is by putting the key in square brackets. As syntactic sugar, when a string key follows the rules of a MiniScript identifier (starts with a letter and contains only letters, numbers, and underscores), you may also access it with dot syntax.

`map = { 3: "test", "foo": 42 } print map[3]map[3] = "more tests"print map[3]print map["foo"]print map.foo  // same as map["foo"] (only for string keys that are valid identifiers) `

Nemerle

This demonstrates two of several constructors, initializing the hashtable with a list of tuples or just specifying an initial capacity.

`using System;using System.Console;using Nemerle.Collections; module AssocArray{    Main() : void    {        def hash1 = Hashtable([(1, "one"), (2, "two"), (3, "three")]);        def hash2 = Hashtable(3);        foreach (e in hash1)            hash2[e.Value] = e.Key;        WriteLine("Enter 1, 2, or 3:");        def entry = int.Parse(ReadLine());        WriteLine(hash1[entry]);    }}`

NetRexx

`/* NetRexx */ options replace format comments java crossref 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 setsay '<hash key="'key1'" value="'hash[key1]'" />' -- Display a value for a key that was set`
Output:
```<hash key="0" value="." />
<hash key="key0" value="value0" />
```

Nim

`import tables var  hash = initTable[string, int]() # empty hash table  hash1: Table[string, int]       # empty hash table (implicit initialization).  hash2 = {"key1": 1, "key2": 2}.toTable # hash table with two keys  hash3 = [("key1", 1), ("key2", 2)].toTable # hash table from tuple array  hash4 = @[("key1", 1), ("key2", 2)].toTable # hash table from tuple seq  value = hash2["key1"] hash["spam"] = 1hash["eggs"] = 2hash["foo"] = 3 echo "hash has ", hash.len, " elements"echo "hash has key foo? ", hash.hasKey("foo")echo "hash has key bar? ", hash.hasKey("bar") echo "iterate pairs:" # iterating over (key, value) pairsfor key, value in hash:  echo key, ": ", value echo "iterate keys:" # iterating over keysfor key in hash.keys:  echo key echo "iterate values:" # iterating over valuesfor key in hash.values:  echo key`
Output:
```hash has 3 elements
hash has key foo? true
hash has key bar? false
iterate pairs:
eggs: 2
foo: 3
spam: 1
iterate keys:
eggs
foo
spam
iterate values:
2
3
1```

Oberon-2

Works with: oo2c Version 2
` MODULE AssociativeArray;IMPORT  ADT:Dictionary,  Object:Boxed,  Out;TYPE  Key = STRING;  Value = Boxed.LongInt; VAR  assocArray: Dictionary.Dictionary(Key,Value);  iterK: Dictionary.IterKeys(Key,Value);  iterV: Dictionary.IterValues(Key,Value);  aux: Value;  k: Key; BEGIN  assocArray := NEW(Dictionary.Dictionary(Key,Value));  assocArray.Set("ten",NEW(Value,10));  assocArray.Set("eleven",NEW(Value,11));   aux := assocArray.Get("ten");  Out.LongInt(aux.value,0);Out.Ln;  aux := assocArray.Get("eleven");  Out.LongInt(aux.value,0);Out.Ln;Out.Ln;   (* Iterate keys *)  iterK := assocArray.IterKeys();  WHILE (iterK.Next(k)) DO    Out.Object(k);Out.Ln  END;   Out.Ln;   (* Iterate values *)  iterV := assocArray.IterValues();  WHILE (iterV.Next(aux)) DO    Out.LongInt(aux.value,0);Out.Ln  END END AssociativeArray.  `

Objeck

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

Associative map

` # create mapmap := StringMap->New();# insertmap->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));# findmap->Find("thirteen")->As(IntHolder)->GetValue()->PrintLine();map->Find("seven")->As(IntHolder)->GetValue()->PrintLine(); `

Hash table

` # create mapmap := StringHash->New();# insertmap->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));# findmap->Find("thirteen")->As(IntHolder)->GetValue()->PrintLine();map->Find("seven")->As(IntHolder)->GetValue()->PrintLine(); `

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.

`NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:    @"Joe Doe", @"name",    [NSNumber numberWithUnsignedInt:42], @"age",    [NSNull null], @"extra",    nil];`

The same as the above with the new literal syntax in clang 3.1+ / Apple LLVM Compiler 4.0+ (XCode 4.4+) :

`NSDictionary *dict = @{    @"name": @"Joe Doe",    @"age": @42,    @"extra": [NSNull null],    };`

To create a mutable dictionary, use NSMutableDictionary:

`NSMutableDictionary *dict = [NSMutableDictionary dictionary];[dict setObject:@"Joe Doe" forKey:@"name"];[dict setObject:[NSNumber numberWithInt:42] forKey:@"age"];`

You can access value with objectForKey:. If a key does not exists, nil is returned.

`NSString *name = [dict objectForKey:@"name"];unsigned age = [dict objectForKey:@"age"] unsignedIntValue];id missing = [dict objectForKey:@"missing"];`

OCaml

Hash table

A simple idiom to create a hash table mapping strings to integers:

`let hash = Hashtbl.create 0;;List.iter (fun (key, value) -> Hashtbl.add hash key value)  ["foo", 5; "bar", 10; "baz", 15];;`

To retrieve a value:

`let bar = Hashtbl.find hash "bar";; (* bar = 10 *)`

To retrieve a value, returning a default if the key is not found:

`let quux = try Hashtbl.find hash "quux" with Not_found -> some_value;;`

Binary tree

A simple idiom to create a persistent binary tree mapping strings to integers:

`module String = struct   type t = string   let compare = Pervasives.compareendmodule 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];;`

To retrieve a value:

`let bar = StringMap.find "bar" map;; (* bar = 10 *)`

To retrieve a value, returning a default if the key is not found:

`let quux = try StringMap.find "quux" map with Not_found -> some_value;;`

Association list

Some list functions allow you to use a list as an associative map, although the access time is O(N) so a Hashtbl or binary tree should be used for larger data-sets.

`let dict = ["foo", 5; "bar", 10; "baz", 15] (* retrieve value *)let bar_num = try List.assoc "bar" dict with Not_found -> 0;; (* see if key exists *)print_endline (if List.mem_assoc "foo" dict then "key found" else "key missing")`

Ol

Associative arrays in Otus Lisp has name "fixed function" (aka "ff") and fully conforms the functional paradigm. It means that there are no ability to change the existing associative array, only get new changed one.

You can use only values as keys (atomic numbers, constants) and, as exception, symbols (symbols are references, but unique). No strings, lists, vectors and other objects can be used directly. In such cases use hashes or similar mechanisms.

` ;;; empty associative array#empty; or short form#e ;;; creating the new empty associative array(define empty-map #empty) ;;; creating associative array with values(define my-map (pairs->ff '(   (1 . 100)   (2 . 200)   (7 . 777))));;; or in short form (available from Ol version 2.1)(define my-map {   1 100   2 200   7 777}) ;;; add new key-value pair to the existing associative array(define my-new-map (put my-map 'the-key 'the-value)) ;;; print our arrays(print empty-map); ==> #() (print my-map); ==> #((1 . 100) (2 . 200) (7 . 777)) (print my-new-map); ==> #((1 . 100) (2 . 200) (7 . 777) (the-key . the-value)) `

ooRexx

ooRexx has multiple classes that create index-to-item associative relationships.

• Directory -- a mapping for a string index to an object instance
• Table -- a mapping for an object index (of any class) to an object instance. Index equality is determined by the "==" method.
• Relation -- a one-to-many mapping for an object index (of any class) to object instances. Index equality is determined by the "==" method.
• IdentityTable -- a mapping for an object index (of any class) to an object instance. Index equality is determined by unique object identity rather than equality.
• Stem -- The class backing ooRexx stem variables, which is also a first-class collection class.

All of the MapCollections are very similar in usage. We'll use Directory for the examples here.

Defining the map:

`map = .directory~newmap["foo"] = 5map["bar"] = 10 map["baz"] = 15 map["foo"] = 6  `

"Putting" a value for a key that already exists ("map["foo"] = 6" in this example) will replace and return the old value for the key.

Retrieving a value:

`item = map["foo"] -- => 6item = map["invalid"] -- => .nil`

Note that it is possible to put `.nil` as a value, so `.nil` being returned as a value is not sufficient for determining that the key is not in the collection. There is a `hasIndex` method for that.

Iterate over keys:

`loop key over map   say keyend  `

Iterate over values:

`loop value over map~allItems    say valueend `

Iterate over key, value pairs:

` s = map~supplierloop while s~available    say s~index "=>" s~item    s~nextend `

OxygenBasic

Not very efficient but the 'find' method could be optimised very easily.

` def n 200 Class AssociativeArray'=====================   indexbase 1  string s[n]  sys    max   method find(string k) as sys  sys i,e  e=max*2  for i=1 to e step 2    if k=s[i] then return i  next  end method   method dat(string k) as string  sys i=find(k)  if i then return s[i+1]  end method   method dat(string k, d) as sys  sys i=find(k)  if i=0 then    if max>=n      print "Array overflow" : return 0    end if     max+=1    i=max*2-1    s[i]=k  end if  s[i+1]=d  return i  end method end class  '===='TEST'==== AssociativeArray A 'fillA.s<={"shoes","LC1",  "ships","LC2",  "sealingwax","LC3",  "cabbages","LC4",  "kings","LC5"}A.max=5'accessprint A.dat("ships")       'result LC2A.dat("computers")="LC99"  'print A.dat("computers")   'result LC99 `

Oz

A mutable map is called a 'dictionary' in Oz:

`declare  Dict = {Dictionary.new}in  Dict.foo := 5  Dict.bar := 10  Dict.baz := 15  Dict.foo := 20   {Inspect Dict}`

'Records' can be consideres immutable maps:

`declare  Rec = name(foo:5 bar:10 baz:20)in  {Inspect Rec}`

PARI/GP

Works with: PARI/GP version 2.8.1+

GP's associative arrays are called maps, and can be created like so:

`M = Map();`

They can be used as follows:

`mapput(M, "key", "value");mapput(M, 17, "different value");mapput(M, "key2", Pi);mapget(M, "key2") \\ returns Pimapisdefined(M, "key3") \\ returns 0mapdelete(M, "key2");`

In PARI the commands are `gtomap`, `mapput`, `mapget`, `mapisdefined`, and `mapdelete`. You can also use the solutions in Associative arrays/Creation/C.

Perl

Hash

Definition:

`# using => key does not need to be quoted unless it contains special charsmy %hash = (  key1 => 'val1',  'key-2' => 2,  three => -238.83,  4 => 'val3',); # using , both key and value need to be quoted if containing something non-numeric in naturemy %hash = (  'key1', 'val1',  'key-2', 2,  'three', -238.83,  4, 'val3',);`

Use:

`print \$hash{key1}; \$hash{key1} = 'val1'; @hash{'key1', 'three'} = ('val1', -238.83);`

HashRef

Definition:

`my \$hashref = { key1 => 'val1',  'key-2' => 2,  three => -238.83,  4 => 'val3',}`

Use:

`print \$hashref->{key1}; \$hashref->{key1} = 'val1'; @{\$hashref}{('key1', 'three')} = ('val1', -238.83);`

Key Types

Keys are strings. Anything else is stringized in Perl's usual ways, which generally means integers work too, but for floating point care might be needed against round-off.

Various `tie` modules implement keys of other types, usually by constructing underlying string keys of suitable nature. For example `Tie::RefHash` allows objects (blessed or unblessed) as keys.

Phix

Associative arrays are supported via just eight simple routines, with no specialised syntax.
Any key can be mapped to any value, and both can be anything (integer|float|string|[nested]sequence, including 0|NULL).

The setd(key,val) procedure is self-explanatory, except for an optional third parameter which is explained below.

The getd(key) function returns the associated data or 0 for non-existent keys: if that might be a valid value see getd_index().

By default, all keys and values are entered into one central dictionary. You can create multiple dictionaries by calling integer tid=new_dict(), and pass that as an additional (final) parameter to the other routines (taking care not to miss any). When you have no further use for it, an entire dictionary can be removed by invoking destroy_dict(tid).

```with javascript_semantics
setd("one",1)
setd(2,"duo")
setd({3,4},{5,"six"})
?getd("one")                                    -- shows 1
?getd({3,4})                                    -- shows {5,"six"}
?getd(2)                                        -- shows "duo"
deld(2)
?getd(2)                                        -- shows 0
```

Phixmonti

`include ..\Utilitys.pmt def getd    /# dict key -- dict data #/    swap 1 get rot find nip    dup if        swap 2 get rot get nip    else        drop "Unfound"    endifenddef def setd    /# dict ( key data ) -- dict #/    1 get var ikey    2 get var idata    drop    1 get ikey find var p drop    p if        2 get idata p set 2 set    else        2 get idata 0 put 2 set        1 get ikey 0 put 1 set    endifenddef ( ( ) ( ) ) ( 1 "one" ) setd( "two" 2 ) setd( PI PI ) setd 1 getd print nl"two" getd print nlPI getd tostr print nl3 getd print `

PHP

`\$array = array();\$array = []; // Simpler form of array initialization\$array['foo'] = 'bar';\$array['bar'] = 'foo'; echo(\$array['foo']); // barecho(\$array['moo']); // Undefined index // Alternative (inline) way\$array2 = array('fruit' => 'apple',                'price' => 12.96,                'colour' => 'green'); // Another alternative (simpler) way\$array2 = ['fruit' => 'apple',                'price' => 12.96,                'colour' => 'green']; // Check if key exists in the associative arrayecho(isset(\$array['foo'])); // Faster, but returns false if the value of the element is set to nullecho(array_key_exists('foo', \$array)); // Slower, but returns true if the value of the element is null`

Iterate over key/value

`foreach(\$array as \$key => \$value){   echo "Key: \$key Value: \$value";}`

Picat

Associative arrays are called "map" in Picat.

`go =>    % Create an empty map   Map = new_map(),   println(Map),    % add some data   Map.put(a,1),   Map.put("picat",2),   Map.put("picat",3), % overwrite values   % Add a new value (a long list of different stuff)   Map.put([a,list,of,different,"things",[including, lists],3.14159],2),   println(Map),    println(a=Map.get(a)), % get a value   println(b=Map.get(b,'default value')), % the second argument to get/2 is the default value    % create a map from a list of values   Map2 = new_map([K=V : {K,V} in zip([a,b,c,d,e,f,g,h],1..8)]),   println(Map2),   println(h=Map2.get(h)),    % Check if there is a value in the map   if not Map2.has_key(z) then     println("no key 'z'")   end,    % keys() and value() returns unsorted list of elements   % so we sort them.   println(keys=Map2.keys().sort()),   println(values=Map2.values().sort()),    % Print the values for the keys that are even   println([K : K=V in Map2, V mod 2=0].sort),     nl. `
Output:
```(map)[]
(map)[a = 1,picat = 3,[a,list,of,different,things,[including,lists],3.14159] = 2]
a = 1
b = default value
(map)[b = 2,a = 1,e = 5,h = 8,f = 6,g = 7,d = 4,c = 3]
h = 8
no key 'z'
keys = abcdefgh
values = [1,2,3,4,5,6,7,8]
bdfh```

PicoLisp

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

`(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`

Pike

Pike provides a built in type called mapping for associative arrays. Any data type including user created classes can be used as indices (aka keys in some other languages) and values.

There are two main ways of indexing a mapping; a[b] or a->b, with variants for "safe" indexing that will not throw error when indexing nonexistent indices. See the documentation for indexing.

indices() and values() can be used to enumerate the contents of an existing mapping.

` mapping m = ([ "apple": "fruit", 17: "seventeen" ]);write("indices: %O\nvalues: %O\n17: %O\n",      indices(m),      values(m),      m[17]); `
Output:
```indices: ({
17,
"apple"
})
values: ({
"seventeen",
"fruit"
})
17: "seventeen"
```

Since any data type can be used nested structures of arbitrary size can be constructed.

` mapping m2 = ([ "car": ([ "ford":17, "volvo":42 ]) ]);write("#ford: %O, #volvo: %O\n",      m2->car->ford,      m2["car"]["volvo"]); `
Output:
```#ford: 17, #volvo: 42
```

PL/I

`*process source xref attributes or(!); assocarr: Proc Options(main); Dcl 1 aa,      2 an Bin Fixed(31) Init(0),      2 pairs(100),       3 key Char(10) Var,       3 val Char(10) Var; Dcl hi Char(10) Value((high(10))); Dcl i  Bin Fixed(31); Dcl k Char(10) Var;  Call aadd('1','spam'); Call aadd('2','eggs'); Call aadd('3','foo'); Call aadd('2','spam'); Call aadd('4','spam');  Put Skip(' '); Put Edit('Iterate over keys')(Skip,a); Do i=1 To an;   k=key(i);   Put Edit('>'!!k!!'< => >'!!aacc(k)!!'<')(Skip,a);   End;  aadd: Proc(k,v); Dcl (k,v) Char(*) Var; If aacc(k)^=hi Then   Put Edit('Key >',k,'< would be a duplicate, not added.')           (Skip,a,a,a); Else Do;   an+=1;   key(an)=k;   val(an)=v;   Put Edit('added >'!!k!!'< -> '!!v!!'<')(Skip,a);   End; End;  aacc: Proc(k) Returns(Char(10) Var); Dcl k Char(*) Var; Dcl v Char(10) Var; Dcl i Bin Fixed(31); Do i=1 To an;   If key(i)=k Then     Return(val(i));   End; Return(hi); End;  End;`
Output:
```added >1< -> spam<
added >2< -> eggs<
added >3< -> foo<
Key >2< would be a duplicate, not added.
added >4< -> spam<

Iterate over keys
>1< => >spam<
>2< => >eggs<
>3< => >foo<
>4< => >spam<  ```

PL/SQL

PL/SQL allows associative arrays defined on two different keys types: Varchar2 or PLS/Integer

Associative Arrays are a PL/SQL only construct. Unlike Oracle Nested Tables or Varrays (the other two types of Oracle collections), associative arrays do not have a corresponding type which can be stored natively in the database. The following code will also show a workaround for this feature.

The following example code is a "record definition", which has nothing to do with associative arrays:-

`DECLARE    type ThisIsNotAnAssocArrayType is record (        myShape VARCHAR2(20),        mySize number,        isActive BOOLEAN    );    assocArray ThisIsNotAnAssocArrayType ;BEGIN    assocArray.myShape := 'circle';     dbms_output.put_line ('assocArray.myShape: ' || assocArray.myShape);    dbms_output.put_line ('assocArray.mySize: ' || assocArray.mySize);END;/`

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 itht('foo') =>;;; Set value corresponding to vector {1 2 3}17 -> ht({1 2 3});;;; print itht({1 2 3}) =>;;; Set value corresponding to number 42 to vector {0 1}{0 1} -> ht(42);;;; print itht(42) => ;;; Iterate over keys printing keys and values.   appproperty(ht,    procedure (key, value);      printf(value, '%p\t');      printf(key, '%p\n');     endprocedure);`

PostScript

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

Potion

`mydictionary = (red=0xff0000, green=0x00ff00, blue=0x0000ff) redblue = "purple"mydictionary put(redblue, 0xff00ff) 255 == mydictionary("blue")65280 == mydictionary("green")16711935 == mydictionary("purple")`

PowerShell

An empty hash table can be created with:

`\$hashtable = @{}`

A hash table can be initialized with key/value pairs:

`\$hashtable = @{    "key1" = "value 1"    key2 = 5            # if the key name has no spaces, no quotes are needed.}`

Individual values can be assigned or replaced by either using a property-style access method or indexing into the table with the given key:

`\$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`

NB. PowerShell compares strings as case-insensitive, that means the hashtable keys 'a' and 'A' are considered the same key. This happens when @{} is turned into a hashtable, but can be overridden by an explicit long-form:

`# Case insensitive keys, both end up as the same key:\$h[email protected]{}\$h['a'] = 1\$h['A'] = 2\$h Name                           Value                                                                                              ----                           -----                                                                                              a                              2      # Case sensitive keys:\$h = New-Object -TypeName System.Collections.Hashtable\$h['a'] = 1\$h['A'] = 2\$h Name                           Value                                                                                              ----                           -----                                                                                              A                              2                                                                                                  a                              1                                                                                                  `

Similarly, values can be retrieved using either syntax:

`\$hashtable.key1     # value 1\$hashtable['key2']  # 5`

It is common to see a hashtable literal used to create an object, by casting it to a new type:

`\$obj = [PSCustomObject]@{    "key1" = "value 1"    key2 = 5            }`

This is a convenience syntax, has less code and runs faster than other ways to create objects.

Prolog

We use the facts table for this purpose.

` mymap(key1,value1).mymap(key2,value2). ?- mymap(key1,V).   V = value1 `

PureBasic

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

`NewMap dict.s()dict("country") = "Germany"Debug dict("country")`

Python

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

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

Numerous methods exist for the mapping type https://docs.python.org/3/library/stdtypes.html#mapping-types-dict

`# empty dictionaryd = {}d['spam'] = 1d['eggs'] = 2   # dictionaries with two keysd1 = {'spam': 1, 'eggs': 2}d2 = dict(spam=1, eggs=2) # dictionaries from tuple listd1 = dict([('spam', 1), ('eggs', 2)])d2 = dict(zip(['spam', 'eggs'], [1, 2])) # iterating over keysfor key in d:  print key, d[key] # iterating over (key, value) pairsfor key, value in d.iteritems():  print key, value`

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

`myDict = { '1': 'a string', 1: 'an integer', 1.0: 'a floating point number', (1,): 'a tuple' }`

(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

R lacks a native representation of key-value pairs, but different structures allow named elements, which provide similar functionality.

environment example

`> env <- new.env()> env[["x"]] <- 123> env[["x"]]`
`[1] 123`
`> index <- "1"> env[[index]] <- "rainfed hay"> env[[index]]`
`[1] "rainfed hay"`
`> env[["1"]]`
`[1] "rainfed hay"`
`> env`
`<environment: 0xb7cd560>`
`> print(env)`
`<environment: 0xb7cd560>`

vector example

`> x <- c(hello=1, world=2, "!"=3)> print(x)`
```hello world     !
1     2     3```
`> print(names(x))`
`[1] "hello" "world" "!"`
`print(unname(x))`
`[1] 1 2 3`

list example

`> a <- list(a=1, b=2, c=3.14, d="xyz")> print(a)`
```\$a
[1] 1

\$b
[1] 2

\$c
[1] 3.14

\$d
[1] "xyz"```
`> print(names(a))`
`[1] "a" "b" "c" "d"`
`> print(unname(a))`
```[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3.14

[[4]]
[1] "xyz"```

Racket

In Racket, hash tables are natively supported and encouraged over association lists in many cases. Data structures that behave like dictionaries support a unified interface.

` #lang racket ;; a-lists(define a-list '((a . 5) (b . 10)))(assoc a-list 'a) ; => '(a . 5) ;; hash tables(define table #hash((a . 5) (b . 10)))(hash-ref table 'a) ; => 5 ;; dictionary interface(dict-ref a-list 'a) ; => 5(dict-ref table 'a)  ; => 5 `

Raku

(formerly Perl 6)

Works with: Rakudo version 2018.03

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.

`my %h1 = key1 => 'val1', 'key-2' => 2, three => -238.83, 4 => 'val3';my %h2 = 'key1', 'val1', 'key-2', 2, 'three', -238.83, 4, 'val3'; # Creating a hash from two lists using a metaoperator. my @a = 1..5;my @b = 'a'..'e';my %h = @a Z=> @b; # 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 Raku's qw (shortcut < ... >) now auto-subscripts. say %h1{'key1'};say %h1<key1>;%h1<key1> = 'val1';%h1<key1 three> = 'val1', -238.83; # Special syntax is no longer necessary to access a hash stored in a scalar. my \$h = {key1 => 'val1', 'key-2' => 2, three => -238.83, 4 => 'val3'};say \$h<key1>; # Keys are of type Str or Int by default. The type of the key can be provided. my %hash{Any}; # same as %hash{*}class C {};my %cash{C};%cash{C.new} = 1;`

Raven

`{ 'a' 1 'b' 2 'c' 3.14 'd' 'xyz' } as a_hasha_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' shorthand6.28 a_hash:'c'        # set key 'c' shorthand`

Null is returned for unknown keys.

Relation

` relation key, valueinsert "foo", "bar"insert "bar", "foo"insert "fruit", "apple"assert unique keyprintselect key == "fruit"print `

assert will show an error, if a key is used twice. However, it not stop the insertion.

key value
foo bar
bar foo
fruit apple
key value
fruit apple

Retro

`with hashTable'hashTable constant table table %{ first = 100 }%table %{ second = "hello, world!" keepString %} table @" first" putntable @" second" puts`

REXX

version 1

Associative arrays are called stem variables in Rexx.

`/* Rexx */ key0 = '0'key1 = 'key0' stem. = '.'                    /* Initialize the associative array 'stem' to '.' */stem.key1 = 'value0'           /* Set a specific key/value pair                  */ Say 'stem.key0= 'stem.key  /* Display a value for a key that wasn't set */Say 'stem.key1= 'stem.key1 /* Display a value for a key that was set    */`
Output:
```stem.key0= .
stem.key1= value0```

version 2

`/*REXX program shows how to set/display values for an associative array.*//*┌────────────────────────────────────────────────────────────────────┐  │ The (below) two REXX statements aren't really necessary, but it    │  │ shows how to define any and all entries in a associative array so  │  │ that if a "key" is used that isn't defined, it can be displayed to │  │ indicate such, or its value can be checked to determine if a       │  │ particular associative array element has been set (defined).       │  └────────────────────────────────────────────────────────────────────┘*/stateC.=' [not defined yet] '          /*sets any/all state capitols.   */stateN.=' [not defined yet] '          /*sets any/all state names.      *//*┌────────────────────────────────────────────────────────────────────┐  │ In REXX, when a "key" is used, it's normally stored (internally)   │  │ as uppercase characters (as in the examples below).  Actually, any │  │ characters can be used,  including blank(s) and non-displayable    │  │ characters  (including '00'x, 'ff'x, commas, periods, quotes, ...).│  └────────────────────────────────────────────────────────────────────┘*/stateC.ca='Sacramento'; stateN.ca='California'stateC.nd='Bismarck'  ; stateN.nd='North Dakota'stateC.mn='St. Paul'  ; stateN.mn='Minnesota'stateC.dc='Washington'; stateN.dc='District of Columbia'stateC.ri='Providence'; stateN.ri='Rhode Island and Providence Plantations' say 'capital of California is' stateC.casay 'capital of Oklahoma is' stateC.okyyy='RI'say 'capital of' stateN.yyy "is" stateC.yyy                                       /*stick a fork in it, we're done.*/`
Output:
```capital of California is Sacramento
capital of Oklahoma is  [not defined yet]
capital of Rhode Island and Providence Plantations is Providence
```

Ring

` # Project  Associative array/Creation myarray = [["one",1],                 ["two",2],                 ["three",3]]see find(myarray,"two",1) + nl           see find(myarray,2,2) + nl `

Output:

```2
2
```

RLaB

Associative arrays are called lists in RLaB.

` x = <<>>;  // create an empty list using strings as identifiers.x.red   = strtod("0xff0000");  // RLaB doesn't deal with hexadecimal numbers directly. Thus wex.green = strtod("0x00ff00");  // convert it to real numbers using ''strtod'' function.x.blue  = strtod("0x0000ff"); // print content of a listfor (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/valueclear (x.red); // we can also use numeric identifiers in the above examplexid = 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,9x = <<>>;  // create an empty listfor (i in 1:5){ x.[i] = i; }  // assign to the element of list ''i'' the real value equal to i.  `

Ruby

A hash object that returns nil for unknown keys

`hash={}hash[666]='devil'hash[777]  # => nilhash[666]  # => 'devil'`

A hash object that returns 'unknown key' for unknown keys

`hash=Hash.new('unknown key')hash[666]='devil'hash[777]  # => 'unknown key'hash[666]  # => 'devil'`

A hash object that returns "unknown key #{key}" for unknown keys

`hash=Hash.new{|h,k| "unknown key #{k}"}hash[666]='devil'hash[777]  # => 'unknown key 777'hash[666]  # => 'devil'`

A hash object that adds "key #{key} was added at #{Time.now}" to the hash the first time an unknown key is seen

`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'`

Rust

`use std::collections::HashMap;fn main() {    let mut olympic_medals = HashMap::new();    olympic_medals.insert("United States", (1072, 859, 749));    olympic_medals.insert("Soviet Union", (473, 376, 355));    olympic_medals.insert("Great Britain", (246, 276, 284));    olympic_medals.insert("Germany", (252, 260, 270));    println!("{:?}", olympic_medals);}`

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; `

Scala

`// immutable mapsvar map = Map(1 -> 2, 3 -> 4, 5 -> 6)map(3) // 4map = map + (44 -> 99) // maps are immutable, so we have to assign the result of adding elementsmap.isDefinedAt(33) // falsemap.isDefinedAt(44) // true`
`// mutable maps (HashSets)import scala.collection.mutable.HashMapval hash = new HashMap[Int, Int]hash(1) = 2hash += (1 -> 2)  // same as hash(1) = 2hash += (3 -> 4, 5 -> 6, 44 -> 99)hash(44) // 99hash.contains(33) // falsehash.isDefinedAt(33) // same as containshash.contains(44) // true`
`// iterate over key/valuehash.foreach {e => println("key "+e._1+" value "+e._2)} // e is a 2 element Tuple// same with for syntaxfor((k,v) <- hash) println("key " + k + " value " + v)`
`// items in map where the key is greater than 3map.filter {k => k._1 > 3} //  Map(5 -> 6, 44 -> 99)// same with for syntaxfor((k, v) <- map; if k > 3) yield (k,v)`

Scheme

Scheme has association lists (alists), which are inefficient, ordered maps with arbitrary keys and values.

`(define my-dict '((a b) (1 hello) ("c" (a b c)))(assoc 'a my-dict)                               ; evaluates to '(a b)`

Hash tables are provided by SRFI-69 [1]. Many Scheme implementation also provide native hash tables.

`(define my-alist '((a b) (1 hello) ("c" (a b c)))(define my-hash (alist->hash-table my-alist))`

The R6RS standard specifies support for hashtables in the standard libraries document.

`#!r6rs (import (rnrs base)        (rnrs hashtables (6))) (define my-hash (make-hashtable equal-hash equal?))(hashtable-set! my-hash 'a 'b)(hashtable-set! my-hash 1 'hello)(hashtable-set! my-hash "c" '(a b c))`

A persistent associative array from scratch

Works with: CHICKEN version 5.3.0
Library: r7rs
Library: srfi-1
Library: srfi-151

Most implementations of associative arrays—including those for Scheme—are for ‘mutable’ arrays, whose previous values are effectively lost whenever an insertion is done. Here instead is a persistent (‘immutable’) implementation, using code from the AVL Tree task. (So performance will be on average logarithmic. Just be aware of that.)

That there are so many implementations of associative arrays for Scheme is partly because making an implementation from scratch is fairly easy. But many approaches are difficult to use if the goal is persistent associative arrays. For instance, if you use a classical hash table, inserting an association would require copying an entire array.

Associate arrays are not part of the Scheme language itself, but are compiler/interpreter or library add-ons. So I feel justified in presenting this sketch of yet another library add-on.

`(cond-expand  (r7rs)  (chicken (import r7rs))) (define-library (avl-trees)   ;;  ;; This library implements ‘persistent’ (that is, ‘immutable’) AVL  ;; trees for R7RS Scheme.  ;;  ;; References:  ;;  ;;   * Niklaus Wirth, 1976. Algorithms + Data Structures =  ;;     Programs. Prentice-Hall, Englewood Cliffs, New Jersey.  ;;  ;;   * Niklaus Wirth, 2004. Algorithms and Data Structures. Updated  ;;     by Fyodor Tkachov, 2014.  ;;  ;; THIS IS A TRIMMED-DOWN VERSION OF MY SOLUTION TO THE AVL TREES  ;; TASK: https://rosettacode.org/wiki/AVL_tree#Scheme  ;;   (export avl)  (export avl?)  (export avl-empty?)  (export avl-insert)  (export avl-search-values)  (export avl-check-usage)   (import (scheme base))  (import (scheme case-lambda))  (import (scheme process-context))  (import (scheme write))   (begin     (define-syntax avl-check-usage      (syntax-rules ()        ((_ pred msg)         (or pred (usage-error msg)))))     (define-record-type <avl>      (%avl key data bal left right)      avl?      (key %key)      (data %data)      (bal %bal)      (left %left)      (right %right))     (define (avl)      (%avl #f #f #f #f #f))     (define (avl-empty? tree)      (avl-check-usage       (avl? tree)       "avl-empty? expects an AVL tree as argument")      (not (%bal tree)))     (define (avl-search-values pred<? tree key)      ;; Return two values: the data matching the key, or #f is the      ;; key is not found; and a second value that is either #f or #t,      ;; depending on whether the key is found.      (define (search p)        (if (not p)            (values #f #f)            (let ((k (%key p)))              (cond ((pred<? key k) (search (%left p)))                    ((pred<? k key) (search (%right p)))                    (else (values (%data p) #t))))))      (avl-check-usage       (procedure? pred<?)       "avl-search-values expects a procedure as first argument")      (if (avl-empty? tree)          (values #f #f)          (search tree)))     (define (avl-insert pred<? tree key data)       (define (search p fix-balance?)        (cond         ((not p)          ;; The key was not found. Make a new node and set          ;; fix-balance?          (values (%avl key data 0 #f #f) #t))          ((pred<? key (%key p))          ;; Continue searching.          (let-values (((p1 fix-balance?)                        (search (%left p) fix-balance?)))            (cond             ((not fix-balance?)              (let ((p^ (%avl (%key p) (%data p) (%bal p)                              p1 (%right p))))                (values p^ #f)))             (else              ;; A new node has been inserted on the left side.              (case (%bal p)                ((1)                 (let ((p^ (%avl (%key p) (%data p) 0                                 p1 (%right p))))                   (values p^ #f)))                ((0)                 (let ((p^ (%avl (%key p) (%data p) -1                                 p1 (%right p))))                   (values p^ fix-balance?)))                ((-1)                 ;; Rebalance.                 (case (%bal p1)                   ((-1)                    ;; A single LL rotation.                    (let* ((p^ (%avl (%key p) (%data p) 0                                     (%right p1) (%right p)))                           (p1^ (%avl (%key p1) (%data p1) 0                                      (%left p1) p^)))                      (values p1^ #f)))                   ((0 1)                    ;; A double LR rotation.                    (let* ((p2 (%right p1))                           (bal2 (%bal p2))                           (p^ (%avl (%key p) (%data p)                                     (- (min bal2 0))                                     (%right p2) (%right p)))                           (p1^ (%avl (%key p1) (%data p1)                                      (- (max bal2 0))                                      (%left p1) (%left p2)))                           (p2^ (%avl (%key p2) (%data p2) 0                                      p1^ p^)))                      (values p2^ #f)))                   (else (internal-error))))                (else (internal-error)))))))          ((pred<? (%key p) key)          ;; Continue searching.          (let-values (((p1 fix-balance?)                        (search (%right p) fix-balance?)))            (cond             ((not fix-balance?)              (let ((p^ (%avl (%key p) (%data p) (%bal p)                              (%left p) p1)))                (values p^ #f)))             (else              ;; A new node has been inserted on the right side.              (case (%bal p)                ((-1)                 (let ((p^ (%avl (%key p) (%data p) 0                                 (%left p) p1)))                   (values p^ #f)))                ((0)                 (let ((p^ (%avl (%key p) (%data p) 1                                 (%left p) p1)))                   (values p^ fix-balance?)))                ((1)                 ;; Rebalance.                 (case (%bal p1)                   ((1)                    ;; A single RR rotation.                    (let* ((p^ (%avl (%key p) (%data p) 0                                     (%left p) (%left p1)))                           (p1^ (%avl (%key p1) (%data p1) 0                                      p^ (%right p1))))                      (values p1^ #f)))                   ((-1 0)                    ;; A double RL rotation.                    (let* ((p2 (%left p1))                           (bal2 (%bal p2))                           (p^ (%avl (%key p) (%data p)                                     (- (max bal2 0))                                     (%left p) (%left p2)))                           (p1^ (%avl (%key p1) (%data p1)                                      (- (min bal2 0))                                      (%right p2) (%right p1)))                           (p2^ (%avl (%key p2) (%data p2) 0                                      p^ p1^)))                      (values p2^ #f)))                   (else (internal-error))))                (else (internal-error)))))))          (else          ;; The key was found; p is an existing node.          (values (%avl key data (%bal p) (%left p) (%right p))                  #f))))       (avl-check-usage       (procedure? pred<?)       "avl-insert expects a procedure as first argument")      (if (avl-empty? tree)          (%avl key data 0 #f #f)          (let-values (((p fix-balance?) (search tree #f)))            p)))     (define (internal-error)      (display "internal error\n" (current-error-port))      (emergency-exit 123))     (define (usage-error msg)      (display "Procedure usage error:\n" (current-error-port))      (display "  " (current-error-port))      (display msg (current-error-port))      (newline (current-error-port))      (exit 1))     )) ;; end library (avl-trees)  (define-library (associative-arrays)   ;;  ;; Persistent associative arrays for R7RS Scheme.  ;;  ;; The story:  ;;   ;; An implementation of associative arrays, where keys are compared  ;; with an ‘equal to’ predicate, typically has three parts:  ;;  ;;    * a hash function, which converts a key to a hash value; and  ;;      the hash value either has a ‘less than’ predicate or can be  ;;      put in a radix tree;  ;;  ;;    * a table keyed by the hash values;  ;;  ;;    * a way to resolve hash value collisions.  ;;  ;; At one extreme is the association list, which can be viewed as  ;; having a hash function that *always* collides. At a nearly  ;; opposite extreme are ideal hash trees, which never have  ;; collisions, but which, towards that end, require hash values to  ;; ‘grow’ on the fly.  ;;  ;; Perhaps the simplest form of associative array having all three  ;; parts is ‘separate chaining’: the hash function generates an  ;; integer modulo some table size; the table itself is an array of  ;; that size; and collisions are resolved by falling back to an  ;; association list.  ;;  ;; Below I use my solution to the AVL Tree task  ;; (https://rosettacode.org/wiki/AVL_tree#Scheme) to implement  ;; *persistent* (that is, ‘immutable’) associative arrays. The hash  ;; function is whatever you want, as long as it produces (what  ;; Scheme regards as) a real number. Hash value collisions are  ;; resolved by falling back to association lists.  ;;   (export assoc-array)  (export assoc-array?)  (export assoc-array-set)  (export assoc-array-ref)   (import (scheme base))  (import (scheme case-lambda))  (import (scheme write))  (import (avl-trees))   (cond-expand    (chicken (import (only (srfi 1) alist-delete)))    ;; Insert whatever you need here for your Scheme.    (else))   (begin     (define-record-type <assoc-array>      (%assoc-array hashfunc pred=? default table)      assoc-array?      (hashfunc %hashfunc)      (pred=? %pred=?)      (default %default)      (table %table))     (define assoc-array      ;; Create an associative array.      (case-lambda        ((hashfunc)         (let ((pred=? equal?)               (default #f))           (assoc-array hashfunc pred=? default)))        ((hashfunc pred=?)         (let ((default #f))           (assoc-array hashfunc pred=? default)))        ((hashfunc pred=? default)         (%assoc-array hashfunc pred=? default (avl)))))     (define (assoc-array-set array key data)      ;; Produce a new associative array that is the same as the input      ;; array except for the given key-data association. The input      ;; array is left unchanged (which is why the procedure is called      ;; ‘assoc-array-set’ rather than ‘assoc-array-set!’).      (let ((hashfunc (%hashfunc array))            (pred=? (%pred=? array))            (default (%default array))            (table (%table array)))        (let ((hash-value (hashfunc key)))          ;; The following could be made more efficient by combining          ;; the ‘search’ and ‘insert’ operations for the AVL tree.          (let*-values              (((alst found?) (avl-search-values < table hash-value)))            (cond             (found?              ;; Add a new entry to the association list. Removal of              ;; any old associations with the key is not strictly              ;; necessary, but without it the associative array will              ;; grow every time you replace an              ;; association. (Alternatively, you could occasionally              ;; clean the associative array of shadowed key              ;; associations.)              (let* ((alst (alist-delete key alst pred=?))                     (alst `((,key . ,data) . ,alst))                     (table (avl-insert < table hash-value alst)))                (%assoc-array hashfunc pred=? default table)))             (else              ;; Start a new association list.              (let* ((alst `((,key . ,data)))                     (table (avl-insert < table hash-value alst)))                (%assoc-array hashfunc pred=? default table))))))))     (define (assoc-array-ref array key)      ;; Return the data associated with the key. If the key is not in      ;; the table, return the associative array’s default data.      (let* ((hashfunc (%hashfunc array))             (hash-value (hashfunc key)))        (let*-values            (((alst found?)              (avl-search-values < (%table array) hash-value)))          (if found?              (let ((pair (assoc key alst (%pred=? array))))                (if pair                    (cdr pair)                    (%default array)))              (%default array)))))     )) ;; end library (associative-arrays)  (cond-expand  (DEMONSTRATION   (begin     (import (scheme base))     (import (scheme write))     (import (srfi 151))     (import (associative-arrays))      ;; I like SpookyHash, but for this demonstration I shall use the     ;; simpler ‘ElfHash’ and define it only for strings. See     ;; https://en.wikipedia.org/w/index.php?title=PJW_hash_function&oldid=997863283     (define (hashfunc s)       (let ((n (string-length s))             (h 0))         (do ((i 0 (+ i 1)))             ((= i n))           (let* ((ch                   ;; If the character is outside the 8-bit range,                   ;; probably I should break it into four bytes, each                   ;; incorporated separately into the hash. For this                   ;; demonstration, I shall simply discard the higher                   ;; bits.                   (bitwise-and (char->integer (string-ref s i))                                #xFF))                  (h^ (+ (arithmetic-shift h 4) ch))                  (high^ (bitwise-and h^ #xF0000000)))             (unless (zero? high^)               (set! h^                 (bitwise-xor h^ (arithmetic-shift high^ -24))))             (set! h (bitwise-and h^ (bitwise-not high^)))))         h))      (let* ((a1 (assoc-array hashfunc))            (a2 (assoc-array-set a1 "A" #\A))            (a3 (assoc-array-set a2 "B" #x42)) ; ASCII ‘B’.            (a4 (assoc-array-set a3 "C" "C")))       (write (assoc-array-ref a1 "A")) (newline)       (write (assoc-array-ref a1 "B")) (newline)       (write (assoc-array-ref a1 "C")) (newline)       (write (assoc-array-ref a2 "A")) (newline)       (write (assoc-array-ref a2 "B")) (newline)       (write (assoc-array-ref a2 "C")) (newline)       (write (assoc-array-ref a3 "A")) (newline)       (write (assoc-array-ref a3 "B")) (newline)       (write (assoc-array-ref a3 "C")) (newline)       (write (assoc-array-ref a4 "A")) (newline)       (write (assoc-array-ref a4 "B")) (newline)       (write (assoc-array-ref a4 "C")) (newline))      ))  (else))`
Output:
```\$ csc -DDEMONSTRATION -R r7rs -X r7rs associative_array-scheme.scm && ./associative_array-scheme
#f
#f
#f
#\A
#f
#f
#\A
66
#f
#\A
66
"C"```

It is easy to add generators to this implementation, by which I mean ‘iterators’ that are themselves executable procedures.

(Afterword. To be honest, I would not use the term ‘associative array’, because ‘array’ implies uniformly constant time access, which even a traditional hash table generally cannot provide. I would call these things ‘maps’—or, if the word ‘map’ is heavily used for something else [such as Scheme’s map procedures], then I would call them ‘dictionaries’.)

Seed7

Seed7 uses the type hash to support associative arrays.

`\$ include "seed7_05.s7i"; # Define hash typeconst type: myHashType is hash [string] integer; # Define hash tablevar 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;`

SenseTalk

Associative arrays in SenseTalk are called property lists, or objects.

`put {} into emptyPlistput an empty property list into emptyPlist2 put {first:"Albert", last:"Einstein"} into Einsteinset Einstein's occupation to "Physicist"put 1879 into Einstein.yearBornput "!!!" after the occupation of Einsteinput Einstein `
Output:
```{first:"Albert", last:"Einstein", occupation:"Physicist!!!", yearBorn:1879}
```

SETL

Associative arrays (referred to in SETL terminology as maps) are implemented as sets whose only members are tuples of length 2. Create such a set:

`m := {['foo', 'a'], ['bar', 'b'], ['baz', 'c']};`

We can then index the set, or map, with the first element of a constituent tuple to return that tuple's second element:

`print( m('bar') );`
Output:
`b`

If the map might contain more than one value associated with the same key, we can return the set of them (in this instance a unit set because the keys are in fact unique):

`print( m{'bar'} );`
Output:
`{b}`

SETL4

` * Iterate over key-value pairs of a map     map = new('map 1:one 2:two 3:three') visit(domain(map),'expr to evaluate for each member') visit(range(map),'expr to evaluate for each member')     next         this = next(map)             :f(done)        out(show(this) ':' show(get(map,this)) :next)    done     loop(d = domain(map)     next        out('next domain entry',next(d))    :s(next)    done     loop(d = range(map)     next        out('next domain entry',next(d))    :s(next)    done `

Sidef

`var hash = Hash.new(    key1 => 'value1',    key2 => 'value2',); # Add a new key-value pairhash{:key3} = 'value3';`

Slate

`Dictionary new*, 'MI' -> 'Michigan', 'MN' -> 'Minnesota'`

Smalltalk

`states := Dictionary new.states at: 'MI' put: 'Michigan'.states at: 'MN' put: 'Minnesota'.`

alternative:

`Dictionary withAssociations:{ 'MI' -> 'Michigan' . 'MN' -> 'Minnesota'}`

SNOBOL4

`	t = table()	t<"red"> = "#ff0000"	t<"green"> = "#00ff00"	t<"blue"> = "#0000ff" 	output = t<"red">	output = t<"blue"> 	output = t<"green">end`

SQL

` REM CREATE a TABLE TO associate KEYS WITH VALUESCREATE TABLE  associative_array ( KEY_COLUMN VARCHAR2(10), VALUE_COLUMN VARCHAR2(100)); .REM INSERT a KEY VALUE PairINSERT (KEY_COLUMN, VALUE_COLUMN) VALUES ( 'VALUE','KEY');.REM Retrieve a KEY VALUE pairSELECT aa.value_column FROM associative_array aa WHERE aa.key_column = 'KEY'; `

SQL PL

Works with: Db2 LUW
version 9.7 or higher.

With SQL PL:

` --#SET TERMINATOR @ SET SERVEROUTPUT ON @ BEGIN DECLARE TYPE ASSOC_ARRAY AS VARCHAR(20) ARRAY [VARCHAR(20)]; DECLARE HASH ASSOC_ARRAY; SET HASH['key1'] = 'val1'; SET HASH['key-2'] = 2; SET HASH['three'] = -238.83; SET HASH[4] = 'val3';  CALL DBMS_OUTPUT.PUT_LINE(HASH['key1']); CALL DBMS_OUTPUT.PUT_LINE(HASH['key-2']); CALL DBMS_OUTPUT.PUT_LINE(HASH['three']); CALL DBMS_OUTPUT.PUT_LINE(HASH[4]); CALL DBMS_OUTPUT.PUT_LINE(HASH['5']);END@ `

Output:

```db2 [email protected]
db2 => BEGIN
...
db2 (cont.) => END @
END
DB21034E  The command was processed as an SQL statement because it was not a
valid Command Line Processor command.  During SQL processing it returned:
SQL20439N  Array index with value "5" is out of range or does not exist.
SQLSTATE=2202E

val1
2
-238.83
val3
```

Stata

`mataa=asarray_create() // Add entriesasarray(a,"one",1)asarray(a,"two",2) // Check existence of keyasarray_contains(a,"two") // Get a vector of all keysasarray_keys(a) // Number of entriesasarray_elements(a) // End Mata sessionend`

Swift

`// make an empty mapvar a = [String: Int]()// orvar b: [String: Int] = [:] // make an empty map with an initial capacityvar c = [String: Int](minimumCapacity: 42) // set a valuec["foo"] = 3 // make a map with a literalvar d = ["foo": 2, "bar": 42, "baz": -1]`

Symsyn

Symsyn implements Hash as a list of strings. Each name/value or key/value pair is stored in another string. The name/value pair is in the format 'name=value', the '=' is reserved.

`  #+ 'name=bob' \$hash   | add to hash #? 'name' \$hash \$S    | find 'name' and return 'bob' in \$S #- 'name' \$hash       | delete 'name=bob' from hash `

Tcl

All arrays in Tcl are associative.

`# Create one element at a time:set hash(foo) 5 # Create in bulk:array set hash {    foo 5    bar 10    baz 15} # Access one element:set value \$hash(foo) # Output all values:foreach key [array names hash] {    puts \$hash(\$key)}`

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

Works with: Tcl version 8.5
`# Create in bulkset d [dict create  foo 5  bar 10  baz 15] # Create/update one elementdict set d foo 5 # Access one valueset value [dict get \$d foo] # Output all valuesdict for {key value} \$d {    puts \$value}# Alternatively...foreach value [dict values \$d] {    puts \$value} # Output the whole dictionary (since it is a Tcl value itself)puts \$d`

Toka

Toka provides associative arrays via a library.

`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 .`

UNIX Shell

Works with: ksh
`typeset -A hashhash=( [key1]=val1 [key2]=val2 )hash[key3]=val3echo "\${hash[key3]}"`
Works with: bash

assigning values is the same as ksh, but to declare the variable as an associative array:

`declare -A hash`

UnixPipes

A key value file can be considered as an associative array

`map='p.map' function init() {cat <<EOF > \$mapapple aboy bcat cdog delephant eEOF} 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 --"} initget cput c cowget cdump`

Vala

Library: Gee
` using Gee; void main(){    var	map = new HashMap<string, int>(); // creates a HashMap with keys of type string, and values of type int                                                     // two methods to set key,value pair    map["one"] = 1;    map["two"] = 2;     map.set("four", 4);    map.set("five", 5);     // two methods of getting key,value pair    stdout.printf("%d\n", map["one"]);     stdout.printf("%d\n", map.get("two"));} `
Compile with flag:
` --pkg gee-1.0 `

VBA

See here in the MSDN the reference for the Dictionary object that can be used in VBA. The following example shows how to create a dictionary, add/remove keys, change a key or a value, and check the existence of a key.

`Option ExplicitSub Test()    Dim h As Object    Set h = CreateObject("Scripting.Dictionary")    h.Add "A", 1    h.Add "B", 2    h.Add "C", 3    Debug.Print h.Item("A")    h.Item("C") = 4    h.Key("C") = "D"    Debug.Print h.exists("C")    h.Remove "B"    Debug.Print h.Count    h.RemoveAll    Debug.Print h.CountEnd Sub`

Vim Script

Dictionary keys are always strings.

`" Creating a dictionary with some initial valueslet dict = {"one": 1, "two": 2} " Retrieving a valuelet two_a = dict["two"]let two_b = dict.twolet two_c = get(dict, "two", "default value for missing key") " Modifying a valuelet dict["one"] = 1.0let dict.two = 2.0 " Adding a new valuelet dict["three"] = 3let dict.four = 4 " Removing a valuelet one = remove(dict, "one")unlet dict["two"]unlet dict.three`

Visual FoxPro

Visual FoxPro has a collection class which can be used for this.

` LOCAL loCol As Collection, k, n, oCLEAR *!* Example using stringsloCol = NEWOBJECT("Collection")loCol.Add("Apples", "A")loCol.Add("Oranges", "O")loCol.Add("Pears", "P")n = loCol.Count? "Items:", n*!* Loop through the collectionk = 1FOR EACH o IN loCol FOXOBJECT    ? o, loCol.GetKey(k)    k = k + 1 ENDFOR	*!* Get an item by its key? loCol("O")?*!* Example using objectsLOCAL loFruits As CollectionloFruits = NEWOBJECT("Collection")loFruits.Add(CREATEOBJECT("fruit", "Apples"), "A")loFruits.Add(CREATEOBJECT("fruit", "Oranges"), "O")loFruits.Add(CREATEOBJECT("fruit", "Pears"), "P")*!* Loop through the collectionk = 1FOR EACH o IN loFruits FOXOBJECT    ? o.Name, loFruits.GetKey(k)    k = k + 1 ENDFOR*!* Get an item name by its key? loFruits("P").Name  DEFINE CLASS fruit As CustomPROCEDURE Init(tcName As String)THIS.Name = tcNameENDPROCENDDEFINE `

Vlang

`fn main() {    // make empty map    mut my_map := map[string]int{}     //s et value    my_map['foo'] = 3     // getting values    y1 := my_map['foo']     // remove keys    my_map.delete('foo')     // make map with values    my_map = {        'foo': 2        'bar': 42        'baz': -1    }}`

Wart

`h <- (table 'a 1 'b 2)h 'a=> 1`

Wren

Wren has a Map class built in.

`var fruit = {}                   // creates an empty mapfruit[1] = "orange"              // associates a key of 1 with "orange"fruit[2] = "apple"               // associates a key of 2 with "apple"System.print(fruit[1])           // retrieves the value with a key of 1 and prints it outfruit.remove(1)                  // removes the entry with a key of 1 from the mapSystem.print(fruit)              // prints the rest of the mapSystem.print()var capitals = {                 // creates a new map with three entries    "France": "Paris",    "Germany": "Berlin",    "Spain": "Madrid"}capitals["Russia"] = "Moscow"    // adds another entrySystem.print(capitals["France"]) // retrieves the "France" entry and prints out its capitalcapitals.remove("France")        // removes the "France" entrySystem.print(capitals)           // prints all remaining entriesSystem.print(capitals.count)     // prints the number of remaining entriesSystem.print(capitals["Sweden"]) // prints the entry for Sweden (null as there isn't one)`
Output:
```orange
{2: apple}

Paris
{Russia: Moscow, Germany: Berlin, Spain: Madrid}
3
null
```

XLISP

XLISP refers to associative arrays as tables. The MAKE-TABLE function returns a new empty table, for instance:

`(define starlings (make-table))`

Values can then be inserted using TABLE-SET!:

`(table-set! starlings "Common starling" "Sturnus vulgaris")(table-set! starlings "Abbot's starling" "Poeoptera femoralis")(table-set! starlings "Cape starling" "Lamprotornis nitens")`

and retrieved using TABLE-REF with their keys:

`(table-ref starlings "Cape starling")`

Output in a REPL:

`"Lamprotornis nitens"`

Other functions provided for tables include MAP-OVER-TABLE-ENTRIES, which takes a table and a function of two arguments and applies the function to each entry (using the key and value as the two arguments), for instance:

`(map-over-table-entries starlings (lambda (x y) (print (string-append x " (Linnaean name " y ")"))))`

Output in a REPL:

```"Abbott's starling (Linnaean name Poeoptera femoralis)"
"Common starling (Linnaean name Sturnus vulgaris)"
"Cape starling (Linnaean name Lamprotornis nitens)"```

XPL0

`include c:\cxpl\stdlib;char Dict(10,10);int  Entries; proc AddEntry(Letter, Greek);   \Insert entry into associative arraychar Letter, Greek;[Dict(Entries,0):= Letter;StrCopy(Greek, @Dict(Entries,1));Entries:= Entries+1;            \(limit checks ignored for simplicity)]; func Lookup(Greek);             \Given Greek name return English letterchar Greek;int  I;[for I:= 0, Entries-1 do    if StrCmp(Greek, @Dict(I,1)) = 0 then return Dict(I,0);return ^?;]; [Entries:= 0;AddEntry(^A, "alpha");AddEntry(^D, "delta");AddEntry(^B, "beta");AddEntry(^C, "gamma");ChOut(0, Lookup("beta"));  CrLf(0);ChOut(0, Lookup("omega")); CrLf(0);]`

For greater speed a hashing algorithm should be used to look up items in a large dictionary, however hashing routines are not provided in the standard library.

Output:
```B
?
```

zkl

`zkl: Dictionary("one",1, "two",2, "three",3)D(two:2,three:3,one:1) zkl: T("one",1, "two",2, "three",3).toDictionary()D(two:2,three:3,one:1)`