This comparison of programming languages (associative arrays) compares the features of associative array data structures or array-lookup processing for over 40 computer programming languages.
The following is a comparison of associative arrays (also "mapping", "hash", and "dictionary") in various programming languages.
AWK has built-in, language-level support for associative arrays.
For example:
phonebook["Sally Smart"]="555-9999"phonebook["John Doe"]="555-1212"phonebook["J. Random Hacker"]="555-1337"
The following code loops through an associated array and prints its contents:
for(nameinphonebook){printname," ",phonebook[name]}
The user can search for elements in an associative array, and delete elements from the array.
The following shows how multi-dimensional associative arrays can be simulated in standard AWK using concatenation and the built-in string-separator variable SUBSEP:
{# for every input linemulti[$1SUBSEP$2]++;}#END{for(xinmulti){split(x,arr,SUBSEP);printarr[1],arr[2],multi[x];}}
There is no standard implementation of associative arrays in C, but a 3rd-party library, C Hash Table, with BSD license, is available. [1]
Another 3rd-party library, uthash, also creates associative arrays from C structures. A structure represents a value, and one of the structure fields serves as the key. [2]
Finally, the GLib library also supports associative arrays, along with many other advanced data types and is the recommended implementation of the GNU Project. [3]
Similar to GLib, Apple's cross-platform Core Foundation framework provides several basic data types. In particular, there are reference-counted CFDictionary and CFMutableDictionary.
C# uses the collection classes provided by the .NET Framework. The most commonly used associative array type is System.Collections.Generic.Dictionary<TKey, TValue>
, which is implemented as a mutable hash table. The relatively new System.Collections.Immutable
package, available in .NET Framework versions 4.5 and above, and in all versions of .NET Core, also includes the System.Collections.Immutable.Dictionary<TKey, TValue>
type, which is implemented using an AVL tree. The methods that would normally mutate the object in-place instead return a new object that represents the state of the original object after mutation.
The following demonstrates three means of populating a mutable dictionary:
Add
method, which adds a key and value and throws an exception if the key already exists in the dictionary;vardictionary=newDictionary<string,string>();dictionary.Add("Sally Smart","555-9999");dictionary["John Doe"]="555-1212";// Not allowed in C#.// dictionary.Item("J. Random Hacker") = "553-1337";dictionary["J. Random Hacker"]="553-1337";
The dictionary can also be initialized during construction using a "collection initializer", which compiles to repeated calls to Add
.
vardictionary=newDictionary<string,string>{{"Sally Smart","555-9999"},{"John Doe","555-1212"},{"J. Random Hacker","553-1337"}};
Values are primarily retrieved using the indexer (which throws an exception if the key does not exist) and the TryGetValue
method, which has an output parameter for the sought value and a Boolean return-value indicating whether the key was found.
varsallyNumber=dictionary["Sally Smart"];
varsallyNumber=(dictionary.TryGetValue("Sally Smart",outvarresult)?result:"n/a";
In this example, the sallyNumber
value will now contain the string "555-9999"
.
A dictionary can be viewed as a sequence of keys, sequence of values, or sequence of pairs of keys and values represented by instances of the KeyValuePair<TKey, TValue>
type, although there is no guarantee of order. For a sorted dictionary, the programmer could choose to use a SortedDictionary<TKey, TValue>
or use the .Sort
LINQ extension method when enumerating.
The following demonstrates enumeration using a foreach loop:
// loop through the collection and display each entry.foreach(KeyValuePair<string,string>kvpindictionary){Console.WriteLine("Phone number for {0} is {1}",kvp.Key,kvp.Value);}
C++ has a form of associative array called std::map
(see Standard Template Library#Containers). One could create a phone-book map with the following code in C++:
#include<map>#include<string>#include<utility>intmain(){std::map<std::string,std::string>phone_book;phone_book.insert(std::make_pair("Sally Smart","555-9999"));phone_book.insert(std::make_pair("John Doe","555-1212"));phone_book.insert(std::make_pair("J. Random Hacker","553-1337"));}
Or less efficiently, as this creates temporary std::string
values:
#include<map>#include<string>intmain(){std::map<std::string,std::string>phone_book;phone_book["Sally Smart"]="555-9999";phone_book["John Doe"]="555-1212";phone_book["J. Random Hacker"]="553-1337";}
With the extension of initialization lists in C++11, entries can be added during a map's construction as shown below:
#include<map>#include<string>intmain(){std::map<std::string,std::string>phone_book{{"Sally Smart","555-9999"},{"John Doe","555-1212"},{"J. Random Hacker","553-1337"}};}
You can iterate through the list with the following code (C++03):
std::map<std::string,std::string>::iteratorcurr,end;for(curr=phone_book.begin(),end=phone_book.end();curr!=end;++curr)std::cout<<curr->first<<" = "<<curr->second<<std::endl;
The same task in C++11:
for(constauto&curr:phone_book)std::cout<<curr.first<<" = "<<curr.second<<std::endl;
Using the structured binding available in C++17:
for(constauto&[name,number]:phone_book){std::cout<<name<<" = "<<number<<std::endl;}
In C++, the std::map
class is templated which allows the data types of keys and values to be different for different map
instances. For a given instance of the map
class the keys must be of the same base type. The same must be true for all of the values. Although std::map
is typically implemented using a self-balancing binary search tree, C++11 defines a second map called std::unordered_map
, which has the algorithmic characteristics of a hash table. This is a common vendor extension to the Standard Template Library (STL) as well, usually called hash_map
, available from such implementations as SGI and STLPort.
Initializing an empty dictionary and adding items in Cobra:
<nowiki/>dicasDictionary<ofString,String>=Dictionary<ofString,String>()dic.add('Sally Smart','555-9999')dic.add('John Doe','555-1212')dic.add('J. Random Hacker','553-1337')assertdic['Sally Smart']=='555-9999'
Alternatively, a dictionary can be initialized with all items during construction:
<nowiki/>dic={'Sally Smart':'555-9999','John Doe':'555-1212','J. Random Hacker':'553-1337'}
The dictionary can be enumerated by a for-loop, but there is no guaranteed order:
<nowiki/>forkey,valindicprint"[key]'s phone number is [val]"
A structure in ColdFusion Markup Language (CFML) is equivalent to an associative array:
dynamicKeyName="John Doe";phoneBook={"Sally Smart"="555-9999","#dynamicKeyName#"="555-4321","J. Random Hacker"="555-1337",UnknownComic="???"};writeOutput(phoneBook.UnknownComic);// ???writeDump(phoneBook);// entire struct
D offers direct support for associative arrays in the core language; such arrays are implemented as a chaining hash table with binary trees. [4] The equivalent example would be:
intmain(){string[string]phone_book;phone_book["Sally Smart"]="555-9999";phone_book["John Doe"]="555-1212";phone_book["J. Random Hacker"]="553-1337";return0;}
Keys and values can be any types, but all the keys in an associative array must be of the same type, and the same goes for dependent values.
Looping through all properties and associated values, and printing them, can be coded as follows:
foreach(key,value;phone_book){writeln("Number for "~key~": "~value);}
A property can be removed as follows:
phone_book.remove("Sally Smart");
Delphi supports several standard containers, including TDictionary<T>:
usesSysUtils,Generics.Collections;varPhoneBook:TDictionary<string,string>;Entry:TPair<string,string>;beginPhoneBook:=TDictionary<string,string>.Create;PhoneBook.Add('Sally Smart','555-9999');PhoneBook.Add('John Doe','555-1212');PhoneBook.Add('J. Random Hacker','553-1337');forEntryinPhoneBookdoWriteln(Format('Number for %s: %s',[Entry.Key,Entry.Value]));end.
Pre-2009 Delphi versions do not support associative arrays directly. Such arrays can be simulated using the TStrings class:
procedureTForm1.Button1Click(Sender:TObject);varDataField:TStrings;i:Integer;beginDataField:=TStringList.Create;DataField.Values['Sally Smart']:='555-9999';DataField.Values['John Doe']:='555-1212';DataField.Values['J. Random Hacker']:='553-1337';// access an entry and display it in a message boxShowMessage(DataField.Values['Sally Smart']);// loop through the associative array fori:=0toDataField.Count-1dobeginShowMessage('Number for '+DataField.Names[i]+': '+DataField.ValueFromIndex[i]);end;DataField.Free;end;
Erlang offers many ways to represent mappings; three of the most common in the standard library are keylists, dictionaries, and maps.
Keylists are lists of tuples, where the first element of each tuple is a key, and the second is a value. Functions for operating on keylists are provided in the lists
module.
PhoneBook=[{"Sally Smith","555-9999"},{"John Doe","555-1212"},{"J. Random Hacker","553-1337"}].
Accessing an element of the keylist can be done with the lists:keyfind/3
function:
{_,Phone}=lists:keyfind("Sally Smith",1,PhoneBook),io:format("Phone number: ~s~n",[Phone]).
Dictionaries are implemented in the dict
module of the standard library. A new dictionary is created using the dict:new/0
function and new key/value pairs are stored using the dict:store/3
function:
PhoneBook1=dict:new(),PhoneBook2=dict:store("Sally Smith","555-9999",Dict1),PhoneBook3=dict:store("John Doe","555-1212",Dict2),PhoneBook=dict:store("J. Random Hacker","553-1337",Dict3).
Such a serial initialization would be more idiomatically represented in Erlang with the appropriate function:
PhoneBook=dict:from_list([{"Sally Smith","555-9999"},{"John Doe","555-1212"},{"J. Random Hacker","553-1337"}]).
The dictionary can be accessed using the dict:find/2
function:
{ok,Phone}=dict:find("Sally Smith",PhoneBook),io:format("Phone: ~s~n",[Phone]).
In both cases, any Erlang term can be used as the key. Variations include the orddict
module, implementing ordered dictionaries, and gb_trees
, implementing general balanced trees.
Maps were introduced in OTP 17.0, [5] and combine the strengths of keylists and dictionaries. A map is defined using the syntax #{ K1 => V1, ... Kn => Vn }
:
PhoneBook=#{"Sally Smith"=>"555-9999","John Doe"=>"555-1212","J. Random Hacker"=>"553-1337"}.
Basic functions to interact with maps are available from the maps
module. For example, the maps:find/2
function returns the value associated with a key:
{ok,Phone}=maps:find("Sally Smith",PhoneBook),io:format("Phone: ~s~n",[Phone]).
Unlike dictionaries, maps can be pattern matched upon:
#{"Sally Smith",Phone}=PhoneBook,io:format("Phone: ~s~n",[Phone]).
Erlang also provides syntax sugar for functional updates—creating a new map based on an existing one, but with modified values or additional keys:
PhoneBook2=PhoneBook#{% the `:=` operator updates the value associated with an existing key"J. Random Hacker":="355-7331",% the `=>` operator adds a new key-value pair, potentially replacing an existing one"Alice Wonderland"=>"555-1865"}
At runtime, F# provides the Collections.Map<'Key,'Value>
type, which is an immutable AVL tree.
The following example calls the Map
constructor, which operates on a list (a semicolon delimited sequence of elements enclosed in square brackets) of tuples (which in F# are comma-delimited sequences of elements).
letnumbers=["Sally Smart","555-9999";"John Doe","555-1212";"J. Random Hacker","555-1337"]|>Map
Values can be looked up via one of the Map
members, such as its indexer or Item
property (which throw an exception if the key does not exist) or the TryFind
function, which returns an option type with a value of Some <result>
, for a successful lookup, or None
, for an unsuccessful one. Pattern matching can then be used to extract the raw value from the result, or a default value can be set.
letsallyNumber=numbers.["Sally Smart"]// orletsallyNumber=numbers.Item("Sally Smart")
letsallyNumber=matchnumbers.TryFind("Sally Smart")with|Some(number)->number|None->"n/a"
In both examples above, the sallyNumber
value would contain the string "555-9999"
.
Because F# is a .NET language, it also has access to features of the .NET Framework, including the System.Collections.Generic.Dictionary<'TKey,'TValue>
type (which is implemented as a hash table), which is the primary associative array type used in C# and Visual Basic. This type may be preferred when writing code that is intended to operate with other languages on the .NET Framework, or when the performance characteristics of a hash table are preferred over those of an AVL tree.
The dict
function provides a means of conveniently creating a .NET dictionary that is not intended to be mutated; it accepts a sequence of tuples and returns an immutable object that implements IDictionary<'TKey,'TValue>
.
letnumbers=["Sally Smart","555-9999";"John Doe","555-1212";"J. Random Hacker","555-1337"]|>dict
When a mutable dictionary is needed, the constructor of System.Collections.Generic.Dictionary<'TKey,'TValue>
can be called directly. See the C# example on this page for additional information.
letnumbers=System.Collections.Generic.Dictionary<string,string>()numbers.Add("Sally Smart","555-9999")numbers.["John Doe"]<-"555-1212"numbers.Item("J. Random Hacker")<-"555-1337"
IDictionary
instances have an indexer that is used in the same way as Map
, although the equivalent to TryFind
is TryGetValue
, which has an output parameter for the sought value and a Boolean return value indicating whether the key was found.
letsallyNumber=letmutableresult=""ifnumbers.TryGetValue("Sally Smart",&result)thenresultelse"n/a"
F# also allows the function to be called as if it had no output parameter and instead returned a tuple containing its regular return value and the value assigned to the output parameter:
letsallyNumber=matchnumbers.TryGetValue("Sally Smart")with|true,number->number|_->"n/a"
A dictionary or map can be enumerated using Seq.map
.
// loop through the collection and display each entry.numbers|>Seq.map(funkvp->printfn"Phone number for %O is %O"kvp.Keykvp.Value)
Visual FoxPro implements mapping with the Collection Class.
mapping = NEWOBJECT("Collection") mapping.Add("Daffodils", "flower2") && Add(object, key) – key must be characterindex = mapping.GetKey("flower2") && returns the index value 1object = mapping("flower2") && returns "Daffodils" (retrieve by key)object = mapping(1) && returns "Daffodils" (retrieve by index)
GetKey returns 0 if the key is not found.
Go has built-in, language-level support for associative arrays, called "maps". A map's key type may only be a boolean, numeric, string, array, struct, pointer, interface, or channel type.
A map type is written: map[keytype]valuetype
Adding elements one at a time:
phone_book:=make(map[string]string)// make an empty mapphone_book["Sally Smart"]="555-9999"phone_book["John Doe"]="555-1212"phone_book["J. Random Hacker"]="553-1337"
A map literal:
phone_book:=map[string]string{"Sally Smart":"555-9999","John Doe":"555-1212","J. Random Hacker":"553-1337",}
Iterating through a map:
// over both keys and valuesforkey,value:=rangephone_book{fmt.Printf("Number for %s: %s\n",key,value)}// over just keysforkey:=rangephone_book{fmt.Printf("Name: %s\n",key)}
The Haskell programming language provides only one kind of associative container – a list of pairs:
m=[("Sally Smart","555-9999"),("John Doe","555-1212"),("J. Random Hacker","553-1337")]main=print(lookup"John Doe"m)
output:
Just "555-1212"
Note that the lookup function returns a "Maybe" value, which is "Nothing" if not found, or "Just 'result'" when found.
The Glasgow Haskell Compiler (GHC), the most commonly used implementation of Haskell, provides two more types of associative containers. Other implementations may also provide these.
One is polymorphic functional maps (represented as immutable balanced binary trees):
importqualifiedData.MapasMm=M.insert"Sally Smart""555-9999"M.emptym'=M.insert"John Doe""555-1212"mm''=M.insert"J. Random Hacker""553-1337"m'main=print(M.lookup"John Doe"m''::MaybeString)
output:
Just "555-1212"
A specialized version for integer keys also exists as Data.IntMap.
Finally, a polymorphic hash table:
importqualifiedData.HashTableasHmain=dom<-H.new(==)H.hashStringH.insertm"Sally Smart""555-9999"H.insertm"John Doe""555-1212"H.insertm"J. Random Hacker""553-1337"foo<-H.lookupm"John Doe"printfoo
output:
Just "555-1212"
Lists of pairs and functional maps both provide a purely functional interface, which is more idiomatic in Haskell. In contrast, hash tables provide an imperative interface in the IO monad.
In Java associative arrays are implemented as "maps", which are part of the Java collections framework. Since J2SE 5.0 and the introduction of generics into Java, collections can have a type specified; for example, an associative array that maps strings to strings might be specified as follows:
Map<String,String>phoneBook=newHashMap<String,String>();phoneBook.put("Sally Smart","555-9999");phoneBook.put("John Doe","555-1212");phoneBook.put("J. Random Hacker","555-1337");
The get
method is used to access a key; for example, the value of the expression phoneBook.get("Sally Smart")
is "555-9999"
. This code uses a hash map to store the associative array, by calling the constructor of the HashMap
class. However, since the code only uses methods common to the interface Map
, a self-balancing binary tree could be used by calling the constructor of the TreeMap
class (which implements the subinterface SortedMap
), without changing the definition of the phoneBook
variable, or the rest of the code, or using other underlying data structures that implement the Map
interface.
The hash function in Java, used by HashMap and HashSet, is provided by the Object.hashCode()
method. Since every class in Java inherits from Object
, every object has a hash function. A class can override the default implementation of hashCode()
to provide a custom hash function more in accordance with the properties of the object.
The Object
class also contains the equals(Object)
method, which tests an object for equality with another object. Hashed data structures in Java rely on objects maintaining the following contract between their hashCode()
and equals()
methods:
For two objects a and b,
a.equals(b)==b.equals(a)ifa.equals(b),thena.hashCode()==b.hashCode()
In order to maintain this contract, a class that overrides equals()
must also override hashCode()
, and vice versa, so that hashCode()
is based on the same properties (or a subset of the properties) as equals()
.
A further contract that a hashed data structure has with the object is that the results of the hashCode()
and equals()
methods will not change once the object has been inserted into the map. For this reason, it is generally a good practice to base the hash function on immutable properties of the object.
Analogously, TreeMap, and other sorted data structures, require that an ordering be defined on the data type. Either the data type must already have defined its own ordering, by implementing the Comparable
interface; or a custom Comparator
must be provided at the time the map is constructed. As with HashMap above, the relative ordering of keys in a TreeMap should not change once they have been inserted into the map.
JavaScript (and its standardized version, ECMAScript) is a prototype-based object-oriented language.
Modern JavaScript handles associative arrays, using the Map
and WeakMap
classes. A map does not contain any keys by default; it only contains what is explicitly put into it. The keys and values can be any type (including functions, objects, or any primitive).
A map can be initialized with all items during construction:
constphoneBook=newMap([["Sally Smart","555-9999"],["John Doe","555-1212"],["J. Random Hacker","553-1337"],]);
Alternatively, you can initialize an empty map and then add items:
constphoneBook=newMap();phoneBook.set("Sally Smart","555-9999");phoneBook.set("John Doe","555-1212");phoneBook.set("J. Random Hacker","553-1337");
Accessing an element of the map can be done with the get
method:
constsallyNumber=phoneBook.get("Sally Smart");
In this example, the value sallyNumber
will now contain the string "555-9999".
The keys in a map are ordered. Thus, when iterating through it, a map object returns keys in order of insertion. The following demonstrates enumeration using a for-loop:
// loop through the collection and display each entry.for(const[name,number]ofphoneBook){console.log(`Phone number for ${name} is ${number}`);}
A key can be removed as follows:
phoneBook.delete("Sally Smart");
An object is similar to a map—both let you set keys to values, retrieve those values, delete keys, and detect whether a value is stored at a key. For this reason (and because there were no built-in alternatives), objects historically have been used as maps.
However, there are important differences that make a map preferable in certain cases. In JavaScript an object is a mapping from property names to values—that is, an associative array with one caveat: the keys of an object must be either a string or a symbol (native objects and primitives implicitly converted to a string keys are allowed). Objects also include one feature unrelated to associative arrays: an object has a prototype, so it contains default keys that could conflict with user-defined keys. So, doing a lookup for a property will point the lookup to the prototype's definition if the object does not define the property.
An object literal is written as { property1: value1, property2: value2, ... }
. For example:
constmyObject={"Sally Smart":"555-9999","John Doe":"555-1212","J. Random Hacker":"553-1337",};
To prevent the lookup from using the prototype's properties, you can use the Object.setPrototypeOf
function:
Object.setPrototypeOf(myObject,null);
As of ECMAScript 5 (ES5), the prototype can also be bypassed by using Object.create(null)
:
constmyObject=Object.create(null);Object.assign(myObject,{"Sally Smart":"555-9999","John Doe":"555-1212","J. Random Hacker":"553-1337",});
If the property name is a valid identifier, the quotes can be omitted, e.g.:
constmyOtherObject={foo:42,bar:false};
Lookup is written using property-access notation, either square brackets, which always work, or dot notation, which only works for identifier keys:
myObject["John Doe"]myOtherObject.foo
You can also loop through all enumerable properties and associated values as follows (a for-in loop):
for(constpropertyinmyObject){constvalue=myObject[property];console.log(`myObject[${property}] = ${value}`);}
Or (a for-of loop):
for(const[property,value]ofObject.entries(myObject)){console.log(`${property} = ${value}`);}
A property can be removed as follows:
deletemyObject["Sally Smart"];
As mentioned before, properties are strings and symbols. Since every native object and primitive can be implicitly converted to a string, you can do:
myObject[1]// key is "1"; note that myObject[1] == myObject["1"]myObject[["a","b"]]// key is "a,b"myObject[{toString(){return"hello world";}}]// key is "hello world"
In modern JavaScript it's considered bad form to use the Array type as an associative array. Consensus is that the Object type and Map
/WeakMap
classes are best for this purpose. The reasoning behind this is that if Array is extended via prototype and Object is kept pristine, for and for-in loops will work as expected on associative 'arrays'. This issue has been brought to the fore by the popularity of JavaScript frameworks that make heavy and sometimes indiscriminate use of prototypes to extend JavaScript's inbuilt types.
See JavaScript Array And Object Prototype Awareness Day for more information on the issue.
In Julia, the following operations manage associative arrays.
Declare dictionary:
phonebook=Dict("Sally Smart"=>"555-9999","John Doe"=>"555-1212","J. Random Hacker"=>"555-1337")
Access element:
phonebook["Sally Smart"]
Add element:
phonebook["New Contact"] = "555-2222"
Delete element:
delete!(phonebook, "Sally Smart")
Get keys and values as iterables:
keys(phonebook) values(phonebook)
In KornShell 93, and compliant shells (ksh93, bash4...), the following operations can be used with associative arrays.
Definition:
typeset-Aphonebook;# ksh93declare-Aphonebook;# bash4phonebook=(["Sally Smart"]="555-9999"["John Doe"]="555-1212"["[[J. Random Hacker]]"]="555-1337");
Dereference:
${phonebook["John Doe"]};
Lisp was originally conceived as a "LISt Processing" language, and one of its most important data types is the linked list, which can be treated as an association list ("alist").
'(("Sally Smart"."555-9999")("John Doe"."555-1212")("J. Random Hacker"."553-1337"))
The syntax (x . y)
is used to indicate a cons
ed pair. Keys and values need not be the same type within an alist. Lisp and Scheme provide operators such as assoc
to manipulate alists in ways similar to associative arrays.
A set of operations specific to the handling of association lists exists for Common Lisp, each of these working non-destructively.
To add an entry the acons
function is employed, creating and returning a new association list. An association list in Common Lisp mimicks a stack, that is, adheres to the last-in-first-out (LIFO) principle, and hence prepends to the list head.
(let((phone-bookNIL))(setfphone-book(acons"Sally Smart""555-9999"phone-book))(setfphone-book(acons"John Doe""555-1212"phone-book))(setfphone-book(acons"J. Random Hacker""555-1337"phone-book)))
This function can be construed as an accommodation for cons
operations. [6]
;; The effect of;; (cons (cons KEY VALUE) ALIST);; is equivalent to;; (acons KEY VALUE ALIST)(let((phone-book'(("Sally Smart"."555-9999")("John Doe"."555-1212"))))(cons(cons"J. Random Hacker""555-1337")phone-book))
Of course, the destructive push
operation also allows inserting entries into an association list, an entry having to constitute a key-value cons in order to retain the mapping's validity.
(push(cons"Dummy""123-4567")phone-book)
Searching for an entry by its key is performed via assoc
, which might be configured for the test predicate and direction, especially searching the association list from its end to its front. The result, if positive, returns the entire entry cons, not only its value. Failure to obtain a matching key leads to a return of the NIL
value.
(assoc"John Doe"phone-book:test#'string=)
Two generalizations of assoc
exist: assoc-if
expects a predicate function that tests each entry's key, returning the first entry for which the predicate produces a non-NIL
value upon invocation. assoc-if-not
inverts the logic, accepting the same arguments, but returning the first entry generating NIL
.
;; Find the first entry whose key equals "John Doe".(assoc-if#'(lambda(key)(string=key"John Doe"))phone-book);; Finds the first entry whose key is neither "Sally Smart" nor "John Doe"(assoc-if-not#'(lambda(key)(memberkey'("Sally Smart""John Doe"):test#'string=))phone-book)
The inverse process, the detection of an entry by its value, utilizes rassoc
.
;; Find the first entry with a value of "555-9999".;; We test the entry string values with the "string=" predicate.(rassoc"555-9999"phone-book:test#'string=)
The corresponding generalizations rassoc-if
and rassoc-if-not
exist.
;; Finds the first entry whose value is "555-9999".(rassoc-if#'(lambda(value)(string=value"555-9999"))phone-book);; Finds the first entry whose value is not "555-9999".(rassoc-if-not#'(lambda(value)(string=value"555-9999"))phone-book)
All of the previous entry search functions can be replaced by general list-centric variants, such as find
, find-if
, find-if-not
, as well as pertinent functions like position
and its derivates.
;; Find an entry with the key "John Doe" and the value "555-1212".(find(cons"John Doe""555-1212")phone-book:test#'equal)
Deletion, lacking a specific counterpart, is based upon the list facilities, including destructive ones.
;; Create and return an alist without any entry whose key equals "John Doe".(remove-if#'(lambda(entry)(string=(carentry)"John Doe"))phone-book)
Iteration is accomplished with the aid of any function that expects a list.
;; Iterate via "map".(mapNIL#'(lambda(entry)(destructuring-bind(key.value)entry(formatT"~&~s => ~s"keyvalue)))phone-book);; Iterate via "dolist".(dolist(entryphone-book)(destructuring-bind(key.value)entry(formatT"~&~s => ~s"keyvalue)))
These being structured lists, processing and transformation operations can be applied without constraints.
;; Return a vector of the "phone-book" values.(map'vector#'cdrphone-book);; Destructively modify the "phone-book" via "map-into".(map-intophone-book#'(lambda(entry)(destructuring-bind(key.value)entry(cons(reversekey)(reversevalue))))phone-book)
Because of their linear nature, alists are used for relatively small sets of data. Common Lisp also supports a hash table data type, and for Scheme they are implemented in SRFI 69. Hash tables have greater overhead than alists, but provide much faster access when there are many elements. A further characteristic is the fact that Common Lisp hash tables do not, as opposed to association lists, maintain the order of entry insertion.
Common Lisp hash tables are constructed via the make-hash-table
function, whose arguments encompass, among other configurations, a predicate to test the entry key. While tolerating arbitrary objects, even heterogeneity within a single hash table instance, the specification of this key :test
function is confined to distinguishable entities: the Common Lisp standard only mandates the support of eq
, eql
, equal
, and equalp
, yet designating additional or custom operations as permissive for concrete implementations.
(let((phone-book(make-hash-table:test#'equal)))(setf(gethash"Sally Smart"phone-book)"555-9999")(setf(gethash"John Doe"phone-book)"555-1212")(setf(gethash"J. Random Hacker"phone-book)"553-1337"))
The gethash
function permits obtaining the value associated with a key.
(gethash"John Doe"phone-book)
Additionally, a default value for the case of an absent key may be specified.
(gethash"Incognito"phone-book'no-such-key)
An invocation of gethash
actually returns two values: the value or substitute value for the key and a boolean indicator, returning T
if the hash table contains the key and NIL
to signal its absence.
(multiple-value-bind(valuecontains-key)(gethash"Sally Smart"phone-book)(ifcontains-key(formatT"~&The associated value is: ~s"value)(formatT"~&The key could not be found.")))
Use remhash
for deleting the entry associated with a key.
(remhash"J. Random Hacker"phone-book)
clrhash
completely empties the hash table.
(clrhashphone-book)
The dedicated maphash
function specializes in iterating hash tables.
(maphash#'(lambda(keyvalue)(formatT"~&~s => ~s"keyvalue))phone-book)
Alternatively, the loop
construct makes provisions for iterations, through keys, values, or conjunctions of both.
;; Iterate the keys and values of the hash table.(loopforkeybeingthehash-keysofphone-bookusing(hash-valuevalue)do(formatT"~&~s => ~s"keyvalue));; Iterate the values of the hash table.(loopforvaluebeingthehash-valuesofphone-bookdo(printvalue))
A further option invokes with-hash-table-iterator
, an iterator-creating macro, the processing of which is intended to be driven by the caller.
(with-hash-table-iterator(entry-generatorphone-book)(loopdo(multiple-value-bind(has-entrykeyvalue)(entry-generator)(ifhas-entry(formatT"~&~s => ~s"keyvalue)(loop-finish)))))
It is easy to construct composite abstract data types in Lisp, using structures or object-oriented programming features, in conjunction with lists, arrays, and hash tables.
LPC implements associative arrays as a fundamental type known as either "map" or "mapping", depending on the driver. The keys and values can be of any type. A mapping literal is written as ([ key_1 : value_1, key_2 : value_2 ])
. Procedural code looks like:
mappingphone_book=([]);phone_book["Sally Smart"]="555-9999";phone_book["John Doe"]="555-1212";phone_book["J. Random Hacker"]="555-1337";
Mappings are accessed for reading using the indexing operator in the same way as they are for writing, as shown above. So phone_book["Sally Smart"] would return the string "555-9999", and phone_book["John Smith"] would return 0. Testing for presence is done using the function member(), e.g. if(member(phone_book, "John Smith")) write("John Smith is listed.\n");
Deletion is accomplished using a function called either m_delete() or map_delete(), depending on the driver: m_delete(phone_book, "Sally Smart");
LPC drivers of the Amylaar family implement multivalued mappings using a secondary, numeric index (other drivers of the MudOS family do not support multivalued mappings.) Example syntax:
mappingphone_book=([:2]);phone_book["Sally Smart",0]="555-9999";phone_book["Sally Smart",1]="99 Sharp Way";phone_book["John Doe",0]="555-1212";phone_book["John Doe",1]="3 Nigma Drive";phone_book["J. Random Hacker",0]="555-1337";phone_book["J. Random Hacker",1]="77 Massachusetts Avenue";
LPC drivers modern enough to support a foreach() construct use it to iterate through their mapping types.
In Lua, "table" is a fundamental type that can be used either as an array (numerical index, fast) or as an associative array.
The keys and values can be of any type, except nil. The following focuses on non-numerical indexes.
A table literal is written as { value, key = value, [index] = value, ["non id string"] = value }
. For example:
phone_book={["Sally Smart"]="555-9999",["John Doe"]="555-1212",["J. Random Hacker"]="553-1337",-- Trailing comma is OK}aTable={-- Table as valuesubTable={5,7.5,k=true},-- key is "subTable"-- Function as value['John Doe']=function(age)ifage<18thenreturn"Young"elsereturn"Old!"endend,-- Table and function (and other types) can also be used as keys}
If the key is a valid identifier (not a reserved word), the quotes can be omitted. Identifiers are case sensitive.
Lookup is written using either square brackets, which always works, or dot notation, which only works for identifier keys:
print(aTable["John Doe"](45))x=aTable.subTable.k
You can also loop through all keys and associated values with iterators or for-loops:
simple={[true]=1,[false]=0,[3.14]=math.pi,x='x',["!"]=42}functionFormatElement(key,value)return"["..tostring(key).."] = "..value..", "end-- Iterate on all keystable.foreach(simple,function(k,v)io.write(FormatElement(k,v))end)print""fork,vinpairs(simple)doio.write(FormatElement(k,v))endprint""k=nilrepeatk,v=next(simple,k)ifk~=nilthenio.write(FormatElement(k,v))enduntilk==nilprint""
An entry can be removed by setting it to nil:
simple.x=nil
Likewise, you can overwrite values or add them:
simple['%']="percent"simple['!']=111
Mathematica and Wolfram Language use the Association expression to represent associative arrays. [7]
phonebook=<|"Sally Smart"->"555-9999","John Doe"->"555-1212","J. Random Hacker"->"553-1337"|>;
To access: [8]
phonebook[[Key["Sally Smart"]]]
If the keys are strings, the Key keyword is not necessary, so:
phonebook[["Sally Smart"]]
To list keys: [9] and values [10]
Keys[phonebook] Values[phonebook]
In MUMPS every array is an associative array. The built-in, language-level, direct support for associative arrays applies to private, process-specific arrays stored in memory called "locals" as well as to the permanent, shared, global arrays stored on disk which are available concurrently to multiple jobs. The name for globals is preceded by the circumflex "^" to distinguish them from local variables.
SET ^phonebook("Sally Smart")="555-9999" ;; storing permanent data SET phonebook("John Doe")="555-1212" ;; storing temporary data SET phonebook("J. Random Hacker")="553-1337" ;; storing temporary data MERGE ^phonebook=phonebook ;; copying temporary data into permanent data
Accessing the value of an element simply requires using the name with the subscript:
WRITE "Phone Number :",^phonebook("Sally Smart"),!
You can also loop through an associated array as follows:
SET NAME="" FOR S NAME=$ORDER(^phonebook(NAME)) QUIT:NAME="" WRITE NAME," Phone Number :",^phonebook(NAME),!
Cocoa and GNUstep, written in Objective-C, handle associative arrays using NSMutableDictionary
(a mutable version of NSDictionary
) class cluster. This class allows assignments between any two objects. A copy of the key object is made before it is inserted into NSMutableDictionary
, therefore the keys must conform to the NSCopying
protocol. When being inserted to a dictionary, the value object receives a retain message to increase its reference count. The value object will receive the release message when it will be deleted from the dictionary (either explicitly or by adding to the dictionary a different object with the same key).
NSMutableDictionary*aDictionary=[[NSMutableDictionaryalloc]init];[aDictionarysetObject:@"555-9999"forKey:@"Sally Smart"];[aDictionarysetObject:@"555-1212"forKey:@"John Doe"];[aDictionarysetObject:@"553-1337"forKey:@"Random Hacker"];
To access assigned objects, this command may be used:
idanObject=[aDictionaryobjectForKey:@"Sally Smart"];
All keys or values can be enumerated using NSEnumerator
:
NSEnumerator*keyEnumerator=[aDictionarykeyEnumerator];idkey;while((key=[keyEnumeratornextObject])){// ... process it here ...}
In Mac OS X 10.5+ and iPhone OS, dictionary keys can be enumerated more concisely using the NSFastEnumeration
construct: [11]
for(idkeyinaDictionary){// ... process it here ...}
What is even more practical, structured data graphs may be easily created using Cocoa, especially NSDictionary
(NSMutableDictionary
). This can be illustrated with this compact example:
NSDictionary*aDictionary=[NSDictionarydictionaryWithObjectsAndKeys:[NSDictionarydictionaryWithObjectsAndKeys:@"555-9999",@"Sally Smart",@"555-1212",@"John Doe",nil],@"students",[NSDictionarydictionaryWithObjectsAndKeys:@"553-1337",@"Random Hacker",nil],@"hackers",nil];
Relevant fields can be quickly accessed using key paths:
idanObject=[aDictionaryvalueForKeyPath:@"students.Sally Smart"];
The OCaml programming language provides three different associative containers. The simplest is a list of pairs:
#letm=["Sally Smart","555-9999";"John Doe","555-1212";"J. Random Hacker","553-1337"];;valm:(string*string)list=[("Sally Smart","555-9999");("John Doe","555-1212");("J. Random Hacker","553-1337")]#List.assoc"John Doe"m;;-:string="555-1212"
The second is a polymorphic hash table:
#letm=Hashtbl.create3;;valm:('_a,'_b)Hashtbl.t=<abstr>#Hashtbl.addm"Sally Smart""555-9999";Hashtbl.addm"John Doe""555-1212";Hashtbl.addm"J. Random Hacker""553-1337";;-:unit=()#Hashtbl.findm"John Doe";;-:string="555-1212"
The code above uses OCaml's default hash function Hashtbl.hash
, which is defined automatically for all types. To use a modified hash function, use the functor interface Hashtbl.Make
to create a module, such as with Map
.
Finally, functional maps (represented as immutable balanced binary trees):
#moduleStringMap=Map.Make(String);;...#letm=StringMap.add"Sally Smart""555-9999"StringMap.emptyletm=StringMap.add"John Doe""555-1212"mletm=StringMap.add"J. Random Hacker""553-1337"m;;valm:stringStringMap.t=<abstr>#StringMap.find"John Doe"m;;-:string="555-1212"
Note that in order to use Map
, you have to provide the functor Map.Make
with a module which defines the key type and the comparison function. The third-party library ExtLib provides a polymorphic version of functional maps, called PMap
, [12] which is given a comparison function upon creation.
Lists of pairs and functional maps both provide a purely functional interface. By contrast, hash tables provide an imperative interface. For many operations, hash tables are significantly faster than lists of pairs and functional maps.
This section needs additional citations for verification .(February 2011) |
The OptimJ programming language is an extension of Java 5. As does Java, Optimj provides maps; but OptimJ also provides true associative arrays. Java arrays are indexed with non-negative integers; associative arrays are indexed with any type of key.
String[String]phoneBook={"Sally Smart"->"555-9999","John Doe"->"555-1212","J. Random Hacker"->"553-1337"};// String[String] is not a java type but an optimj type:// associative array of strings indexed by strings.// iterate over the valuesfor(Stringnumber:phoneBook){System.out.println(number);}// The previous statement prints: "555-9999" "555-1212" "553-1337"// iterate over the keysfor(Stringname:phoneBook.keys){System.out.println(name+" -> "+phoneBook[name]);}// phoneBook[name] access a value by a key (it looks like java array access)// i.e. phoneBook["John Doe"] returns "555-1212"
Of course, it is possible to define multi-dimensional arrays, to mix Java arrays and associative arrays, to mix maps and associative arrays.
int[String][][double]a;java.util.Map<String[Object],Integer>b;
Perl 5 has built-in, language-level support for associative arrays. Modern Perl refers to associative arrays as hashes; the term associative array is found in older documentation but is considered somewhat archaic. Perl 5 hashes are flat: keys are strings and values are scalars. However, values may be references to arrays or other hashes, and the standard Perl 5 module Tie::RefHash enables hashes to be used with reference keys.
A hash variable is marked by a %
sigil, to distinguish it from scalar, array, and other data types. A hash literal is a key-value list, with the preferred form using Perl's =>
token, which is semantically mostly identical to the comma and makes the key-value association clearer:
my%phone_book=('Sally Smart'=>'555-9999','John Doe'=>'555-1212','J. Random Hacker'=>'553-1337',);
Accessing a hash element uses the syntax $hash_name{$key}
– the key is surrounded by curly braces and the hash name is prefixed by a $
, indicating that the hash element itself is a scalar value, even though it is part of a hash. The value of $phone_book{'John Doe'}
is '555-1212'
. The %
sigil is only used when referring to the hash as a whole, such as when asking for keys %phone_book
.
The list of keys and values can be extracted using the built-in functions keys
and values
, respectively. So, for example, to print all the keys of a hash:
foreach$name(keys%phone_book){print$name,"\n";}
One can iterate through (key, value) pairs using the each
function:
while(($name,$number)=each%phone_book){print'Number for ',$name,': ',$number,"\n";}
A hash "reference", which is a scalar value that points to a hash, is specified in literal form using curly braces as delimiters, with syntax otherwise similar to specifying a hash literal:
my$phone_book={'Sally Smart'=>'555-9999','John Doe'=>'555-1212','J. Random Hacker'=>'553-1337',};
Values in a hash reference are accessed using the dereferencing operator:
print$phone_book->{'Sally Smart'};
When the hash contained in the hash reference needs to be referred to as a whole, as with the keys
function, the syntax is as follows:
foreach$name(keys%{$phone_book}){print'Number for ',$name,': ',$phone_book->{$name},"\n";}
Perl 6, renamed as "Raku", also has built-in, language-level support for associative arrays, which are referred to as hashes or as objects performing the "associative" role. As in Perl 5, Perl 6 default hashes are flat: keys are strings and values are scalars. One can define a hash to not coerce all keys to strings automatically: these are referred to as "object hashes", because the keys of such hashes remain the original object rather than a stringification thereof.
A hash variable is typically marked by a %
sigil, to visually distinguish it from scalar, array, and other data types, and to define its behaviour towards iteration. A hash literal is a key-value list, with the preferred form using Perl's =>
token, which makes the key-value association clearer:
my%phone-book = 'Sally Smart' => '555-9999', 'John Doe' => '555-1212', 'J. Random Hacker' => '553-1337', ;
Accessing a hash element uses the syntax %hash_name{$key}
– the key is surrounded by curly braces and the hash name (note that the sigil does not change, contrary to Perl 5). The value of %phone-book{'John Doe'}
is '555-1212'
.
The list of keys and values can be extracted using the built-in functions keys
and values
, respectively. So, for example, to print all the keys of a hash:
for%phone-book.keys -> $name { say$name; }
By default, when iterating through a hash, one gets key–value pairs.
for%phone-book -> $entry { say"Number for $entry.key(): $entry.value()"; # using extended interpolation features }
It is also possible to get alternating key values and value values by using the kv
method:
for%phone-book.kv -> $name, $number { say"Number for $name: $number"; }
Raku doesn't have any references. Hashes can be passed as single parameters that are not flattened. If you want to make sure that a subroutine only accepts hashes, use the % sigil in the Signature.
sublist-phone-book(%pb) { for%pb.kv -> $name, $number { say"Number for $name: $number"; } } list-phone-book(%phone-book);
In compliance with gradual typing, hashes may be subjected to type constraints, confining a set of valid keys to a certain type.
# Define a hash whose keys may only be integer numbers ("Int" type).my%numbersWithNames{Int}; # Keys must be integer numbers, as in this case.%numbersWithNames.push(1 => "one"); # This will cause an error, as strings as keys are invalid.%numbersWithNames.push("key" => "two");
PHP's built-in array type is, in reality, an associative array. Even when using numerical indexes, PHP internally stores arrays as associative arrays. [13] So, PHP can have non-consecutively numerically indexed arrays. The keys have to be of integer (floating point numbers are truncated to integer) or string type, while values can be of arbitrary types, including other arrays and objects. The arrays are heterogeneous: a single array can have keys of different types. PHP's associative arrays can be used to represent trees, lists, stacks, queues, and other common data structures not built into PHP.
An associative array can be declared using the following syntax:
$phonebook=array();$phonebook['Sally Smart']='555-9999';$phonebook['John Doe']='555-1212';$phonebook['J. Random Hacker']='555-1337';// or$phonebook=array('Sally Smart'=>'555-9999','John Doe'=>'555-1212','J. Random Hacker'=>'555-1337',);// or, as of PHP 5.4$phonebook=['Sally Smart'=>'555-9999','John Doe'=>'555-1212','J. Random Hacker'=>'555-1337',];// or$phonebook['contacts']['Sally Smart']['number']='555-9999';$phonebook['contacts']['John Doe']['number']='555-1212';$phonebook['contacts']['J. Random Hacker']['number']='555-1337';
PHP can loop through an associative array as follows:
foreach($phonebookas$name=>$number){echo'Number for ',$name,': ',$number,"\n";}// For the last array example it is used like thisforeach($phonebook['contacts']as$name=>$num){echo'Name: ',$name,', number: ',$num['number'],"\n";}
PHP has an extensive set of functions to operate on arrays. [14]
Associative arrays that can use objects as keys, instead of strings and integers, can be implemented with the SplObjectStorage
class from the Standard PHP Library (SPL). [15]
Pike has built-in support for associative arrays, which are referred to as mappings. Mappings are created as follows:
mapping(string:string)phonebook=(["Sally Smart":"555-9999","John Doe":"555-1212","J. Random Hacker":"555-1337"]);
Accessing and testing for presence in mappings is done using the indexing operator. So phonebook["Sally Smart"]
would return the string "555-9999"
, and phonebook["John Smith"]
would return 0.
Iterating through a mapping can be done using foreach
:
foreach(phonebook;stringkey;stringvalue){write("%s:%s\n",key,value);}
Or using an iterator object:
Mapping.Iteratori=get_iterator(phonebook);while(i->index()){write("%s:%s\n",i->index(),i->value());i->next();}
Elements of a mapping can be removed using m_delete
, which returns the value of the removed index:
stringsallys_number=m_delete(phonebook,"Sally Smart");
In PostScript, associative arrays are called dictionaries. In Level 1 PostScript they must be created explicitly, but Level 2 introduced direct declaration using a double-angled-bracket syntax:
% Level 1 declaration3dictdupbegin/red(rouge)def/green(vert)def/blue(bleu)defend% Level 2 declaration<</red(rot)/green(gruen)/blue(blau)>>% Both methods leave the dictionary on the operand stack
Dictionaries can be accessed directly, using get
, or implicitly, by placing the dictionary on the dictionary stack using begin
:
% With the previous two dictionaries still on the operand stack/redgetprint% outputs 'rot'begingreenprint% outputs 'vert'end
Dictionary contents can be iterated through using forall
, though not in any particular order:
% Level 2 example<</This1/That2/Other3>>{exch=print( is )print==}forall
Which may output:
Thatis2Thisis1Otheris3
Dictionaries can be augmented (up to their defined size only in Level 1) or altered using put
, and entries can be removed using undef
:
% define a dictionary for easy reuse:/MyDict<</rouge(red)/vert(gruen)>>def% add to itMyDict/bleu(blue)put% change itMyDict/vert(green)put% remove somethingMyDict/rougeundef
Some versions of Prolog include dictionary ("dict") utilities. [16]
In Python, associative arrays are called "dictionaries". Dictionary literals are delimited by curly braces:
phonebook={"Sally Smart":"555-9999","John Doe":"555-1212","J. Random Hacker":"553-1337",}
Dictionary items can be accessed using the array indexing operator:
>>>phonebook["Sally Smart"]'555-9999'
Loop iterating through all the keys of the dictionary:
>>>forkeyinphonebook:...print(key,phonebook[key])SallySmart555-9999J.RandomHacker553-1337JohnDoe555-1212
Iterating through (key, value) tuples:
>>>forkey,valueinphonebook.items():...print(key,value)SallySmart555-9999J.RandomHacker553-1337JohnDoe555-1212
Dictionary keys can be individually deleted using the del
statement. The corresponding value can be returned before the key-value pair is deleted using the "pop" method of "dict" type:
>>>delphonebook["John Doe"]>>>val=phonebook.pop("Sally Smart")>>>phonebook.keys()# Only one key left['J. Random Hacker']
Python 2.7 and 3.x also support dict comprehensions (similar to list comprehensions), a compact syntax for generating a dictionary from any iterator:
>>>square_dict={i:i*iforiinrange(5)}>>>square_dict{0:0,1:1,2:4,3:9,4:16}>>>{key:valueforkey,valueinphonebook.items()if"J"inkey}{'J. Random Hacker':'553-1337','John Doe':'555-1212'}
Strictly speaking, a dictionary is a super-set of an associative array, since neither the keys or values are limited to a single datatype. One could think of a dictionary as an "associative list" using the nomenclature of Python. For example, the following is also legitimate:
phonebook={"Sally Smart":"555-9999","John Doe":None,"J. Random Hacker":-3.32,14:"555-3322",}
The dictionary keys must be of an immutable data type. In Python, strings are immutable due to their method of implementation.
In Red the built-in map!
[17] datatype provides an associative array that maps values of word, string, and scalar key types to values of any type. A hash table is used internally for lookup.
A map can be written as a literal, such as #(key1 value1 key2 value2 ...)
, or can be created using make map! [key1 value1 key2 value2 ...]
:
Red[Title:"My map"]my-map:makemap!["Sally Smart""555-9999""John Doe""555-1212""J. Random Hacker""553-1337"]; Red preserves case for both keys and values, however lookups are case insensitive by default; it is possible to force case sensitivity using the <code>/case</code> refinement for <code>select</code> and <code>put</code>.; It is of course possible to use <code>word!</code> values as keys, in which case it is generally preferred to use <code>set-word!</code> values when creating the map, but any word type can be used for lookup or creation.my-other-map:makemap![foo:42bar:false]; Notice that the block is not reduced or evaluated in any way, therefore in the above example the key <code>bar</code> is associated with the <code>word!</code> <code>false</code> rather than the <code>logic!</code> value false; literal syntax can be used if the latter is desired:my-other-map:makemap![foo:42bar:#[false]]; or keys can be added after creation:my-other-map:makemap![foo:42]my-other-map/bar:false; Lookup can be written using <code>path!</code> notation or using the <code>select</code> action:selectmy-map"Sally Smart"my-other-map/foo; You can also loop through all keys and values with <code>foreach</code>:foreach[keyvalue]my-map[print[key"is associated to"value]]; A key can be removed using <code>remove/key</code>:remove/keymy-map"Sally Smart"
In REXX, associative arrays are called "stem variables" or "Compound variables".
KEY='Sally Smart' PHONEBOOK.KEY='555-9999' KEY='John Doe' PHONEBOOK.KEY='555-1212' KEY='J. Random Hacker' PHONEBOOK.KEY='553-1337'
Stem variables with numeric keys typically start at 1 and go up from there. The 0-key stem variable by convention contains the total number of items in the stem:
NAME.1='Sally Smart' NAME.2='John Doe' NAME.3='J. Random Hacker' NAME.0=3
REXX has no easy way of automatically accessing the keys of a stem variable; and typically the keys are stored in a separate associative array, with numeric keys.
In Ruby a hash table is used as follows:
phonebook={'Sally Smart'=>'555-9999','John Doe'=>'555-1212','J. Random Hacker'=>'553-1337'}phonebook['John Doe']
Ruby supports hash looping and iteration with the following syntax:
irb(main):007:0> ### iterate over keys and valuesirb(main):008:0* phonebook.each{|key,value|putskey+" => "+value}Sally Smart => 555-9999John Doe => 555-1212J. Random Hacker => 553-1337=> {"Sally Smart"=>"555-9999", "John Doe"=>"555-1212", "J. Random Hacker"=>"553-1337"}irb(main):009:0> ### iterate keys onlyirb(main):010:0* phonebook.each_key{|key|putskey}Sally SmartJohn DoeJ. Random Hacker=> {"Sally Smart"=>"555-9999", "John Doe"=>"555-1212", "J. Random Hacker"=>"553-1337"}irb(main):011:0> ### iterate values onlyirb(main):012:0* phonebook.each_value{|value|putsvalue}555-9999555-1212553-1337=> {"Sally Smart"=>"555-9999", "John Doe"=>"555-1212", "J. Random Hacker"=>"553-1337"}
Ruby also supports many other useful operations on hashes, such as merging hashes, selecting or rejecting elements that meet some criteria, inverting (swapping the keys and values), and flattening a hash into an array.
The Rust standard library provides a hash map (std::collections::HashMap
) and a B-tree map (std::collections::BTreeMap
). They share several methods with the same names, but have different requirements for the types of keys that can be inserted. The HashMap
requires keys to implement the Eq
(equivalence relation) and Hash
(hashability) traits and it stores entries in an unspecified order, and the BTreeMap
requires the Ord
(total order) trait for its keys and it stores entries in an order defined by the key type. The order is reflected by the default iterators.
usestd::collections::HashMap;letmutphone_book=HashMap::new();phone_book.insert("Sally Smart","555-9999");phone_book.insert("John Doe","555-1212");phone_book.insert("J. Random Hacker","555-1337");
The default iterators visit all entries as tuples. The HashMap
iterators visit entries in an unspecified order and the BTreeMap
iterator visits entries in the order defined by the key type.
for(name,number)in&phone_book{println!("{} {}",name,number);}
There is also an iterator for keys:
fornameinphone_book.keys(){println!("{}",name);}
S-Lang has an associative array type:
phonebook = Assoc_Type[]; phonebook["Sally Smart"] = "555-9999" phonebook["John Doe"] = "555-1212" phonebook["J. Random Hacker"] = "555-1337"
You can also loop through an associated array in a number of ways:
foreach name (phonebook) { vmessage ("%s %s", name, phonebook[name]); }
To print a sorted-list, it is better to take advantage of S-lang's strong support for standard arrays:
keys = assoc_get_keys(phonebook); i = array_sort(keys); vals = assoc_get_values(phonebook); array_map (Void_Type, &vmessage, "%s %s", keys[i], vals[i]);
Scala provides an immutable Map
class as part of the scala.collection
framework:
valphonebook=Map("Sally Smart"->"555-9999","John Doe"->"555-1212","J. Random Hacker"->"553-1337")
Scala's type inference will decide that this is a Map[String, String]
. To access the array:
phonebook.get("Sally Smart")
This returns an Option
type, Scala's equivalent of the Maybe monad in Haskell.
In Smalltalk a Dictionary
is used:
phonebook:=Dictionarynew.phonebookat:'Sally Smart'put:'555-9999'.phonebookat:'John Doe'put:'555-1212'.phonebookat:'J. Random Hacker'put:'553-1337'.
To access an entry the message #at:
is sent to the dictionary object:
phonebookat:'Sally Smart'
Which gives:
'555-9999'
A dictionary hashes, or compares, based on equality and marks both key and value as strong references. Variants exist in which hash/compare on identity (IdentityDictionary) or keep weak references (WeakKeyDictionary / WeakValueDictionary). Because every object implements #hash, any object can be used as key (and of course also as value).
SNOBOL is one of the first (if not the first) programming languages to use associative arrays. Associative arrays in SNOBOL are called Tables.
PHONEBOOK=TABLE()PHONEBOOK['Sally Smart']='555-9999'PHONEBOOK['John Doe']='555-1212'PHONEBOOK['J. Random Hacker']='553-1337'
The SML'97 standard of the Standard ML programming language does not provide any associative containers. However, various implementations of Standard ML do provide associative containers.
The library of the popular Standard ML of New Jersey (SML/NJ) implementation provides a signature (somewhat like an "interface"), ORD_MAP
, which defines a common interface for ordered functional (immutable) associative arrays. There are several general functors—BinaryMapFn
, ListMapFn
, RedBlackMapFn
, and SplayMapFn
—that allow you to create the corresponding type of ordered map (the types are a self-balancing binary search tree, sorted association list, red–black tree, and splay tree, respectively) using a user-provided structure to describe the key type and comparator. The functor returns a structure in accordance with the ORD_MAP
interface. In addition, there are two pre-defined modules for associative arrays that employ integer keys: IntBinaryMap
and IntListMap
.
-structureStringMap=BinaryMapFn(structtypeord_key=stringvalcompare=String.compareend);structureStringMap:ORD_MAP-valm=StringMap.insert(StringMap.empty,"Sally Smart","555-9999")valm=StringMap.insert(m,"John Doe","555-1212")valm=StringMap.insert(m,"J. Random Hacker","553-1337");valm=T{cnt=3,key="John Doe",left=T{cnt=1,key="J. Random Hacker",left=E,right=E,value="553-1337"},right=T{cnt=1,key="Sally Smart",left=E,right=E,value="555-9999"},value="555-1212"}:stringStringMap.map-StringMap.find(m,"John Doe");valit=SOME"555-1212":stringoption
SML/NJ also provides a polymorphic hash table:
-exceptionNotFound;exceptionNotFound-valm:(string,string)HashTable.hash_table=HashTable.mkTable(HashString.hashString,op=)(3,NotFound);valm=HT{eq_pred=fn,hash_fn=fn,n_items=ref0,not_found=NotFound(-),table=ref[|NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,...|]}:(string,string)HashTable.hash_table-HashTable.insertm("Sally Smart","555-9999");valit=():unit-HashTable.insertm("John Doe","555-1212");valit=():unit-HashTable.insertm("J. Random Hacker","553-1337");valit=():unitHashTable.findm"John Doe";(* returns NONE if not found *)valit=SOME"555-1212":stringoption-HashTable.lookupm"John Doe";(* raises the exception if not found *)valit="555-1212":string
Monomorphic hash tables are also supported, using the HashTableFn
functor.
Another Standard ML implementation, Moscow ML, also provides some associative containers. First, it provides polymorphic hash tables in the Polyhash
structure. Also, some functional maps from the SML/NJ library above are available as Binarymap
, Splaymap
, and Intmap
structures.
There are two Tcl facilities that support associative-array semantics. An "array" is a collection of variables. A "dict" is a full implementation of associative arrays.
set{phonebook(SallySmart)}555-9999setjohn{JohnDoe}setphonebook($john)555-1212set{phonebook(J.RandomHacker)}553-1337
If there is a space character in the variable name, the name must be grouped using either curly brackets (no substitution performed) or double quotes (substitution is performed).
Alternatively, several array elements can be set by a single command, by presenting their mappings as a list (words containing whitespace are braced):
arraysetphonebook[list{SallySmart}555-9999{JohnDoe}555-1212{J.RandomHacker}553-1337]
To access one array entry and put it to standard output:
puts$phonebook(Sally\Smart)
Which returns this result:
555-9999
To retrieve the entire array as a dictionary:
arraygetphonebook
The result can be (order of keys is unspecified, not because the dictionary is unordered, but because the array is):
{SallySmart}555-9999{J.RandomHacker}553-1337{JohnDoe}555-1212
setphonebook[dictcreate{SallySmart}555-9999{JohnDoe}555-1212{J.RandomHacker}553-1337]
To look up an item:
dictget$phonebook{JohnDoe}
To iterate through a dict:
foreach{namenumber}$phonebook{puts"name: $name\nnumber: $number"}
Visual Basic can use the Dictionary class from the Microsoft Scripting Runtime (which is shipped with Visual Basic 6). There is no standard implementation common to all versions:
' Requires a reference to SCRRUN.DLL in Project PropertiesDimphoneBookAsNewDictionaryphoneBook.Add"Sally Smart","555-9999"phoneBook.Item("John Doe")="555-1212"phoneBook("J. Random Hacker")="553-1337"ForEachnameInphoneBookMsgBoxname&" = "&phoneBook(name)Next
Visual Basic .NET uses the collection classes provided by the .NET Framework.
The following code demonstrates the creation and population of a dictionary (see the C# example on this page for additional information):
DimdicAsNewSystem.Collections.Generic.Dictionary(OfString,String)dic.Add("Sally Smart","555-9999")dic("John Doe")="555-1212"dic.Item("J. Random Hacker")="553-1337"
An alternate syntax would be to use a collection initializer, which compiles down to individual calls to Add
:
DimdicAsNewSystem.Collections.Dictionary(OfString,String)From{{"Sally Smart","555-9999"},{"John Doe","555-1212"},{"J. Random Hacker","553-1337"}}
Example demonstrating access (see C# access):
DimsallyNumber=dic("Sally Smart")' orDimsallyNumber=dic.Item("Sally Smart")
DimresultAsString=NothingDimsallyNumber=If(dic.TryGetValue("Sally Smart",result),result,"n/a")
Example demonstrating enumeration (see #C# enumeration):
' loop through the collection and display each entry.ForEachkvpAsKeyValuePair(OfString,String)IndicConsole.WriteLine("Phone number for {0} is {1}",kvp.Key,kvp.Value)Next
Unlike many other command line interpreters, Windows PowerShell has built-in, language-level support for defining associative arrays:
$phonebook=@{'Sally Smart'='555-9999';'John Doe'='555-1212';'J. Random Hacker'='553-1337'}
As in JavaScript, if the property name is a valid identifier, the quotes can be omitted:
$myOtherObject=@{foo=42;bar=$false}
Entries can be separated by either a semicolon or a newline:
$myOtherObject=@{foo=42bar=$false;zaz=3}
Keys and values can be any .NET object type:
$now=[DateTime]::Now$tomorrow=$now.AddDays(1)$ProcessDeletionSchedule=@{(Get-Processnotepad)=$now(Get-Processcalc)=$tomorrow}
It is also possible to create an empty associative array and add single entries, or even other associative arrays, to it later on:
$phonebook=@{}$phonebook+=@{'Sally Smart'='555-9999'}$phonebook+=@{'John Doe'='555-1212';'J. Random Hacker'='553-1337'}
New entries can also be added by using the array index operator, the property operator, or the Add()
method of the underlying .NET object:
$phonebook=@{}$phonebook['Sally Smart']='555-9999'$phonebook.'John Doe'='555-1212'$phonebook.Add('J. Random Hacker','553-1337')
To dereference assigned objects, the array index operator, the property operator, or the parameterized property Item()
of the .NET object can be used:
$phonebook['Sally Smart']$phonebook.'John Doe'$phonebook.Item('J. Random Hacker')
You can loop through an associative array as follows:
$phonebook.Keys|foreach{"Number for {0}: {1}"-f$_,$phonebook.$_}
An entry can be removed using the Remove()
method of the underlying .NET object:
$phonebook.Remove('Sally Smart')
Hash tables can be added:
$hash1=@{a=1;b=2}$hash2=@{c=3;d=4}$hash3=$hash1+$hash2
This section needs expansion. You can help by adding to it. (September 2010) |
Many data serialization formats also support associative arrays (see this table)
In JSON, associative arrays are also referred to as objects. Keys can only be strings.
{"Sally Smart":"555-9999","John Doe":"555-1212","J. Random Hacker":"555-1337"}
YAML associative arrays are also called map elements or key-value pairs. YAML places no restrictions on the types of keys; in particular, they are not restricted to being scalar or string values.
Sally Smart:555-9999John Doe:555-1212J. Random Hacker:555-1337
In computer science, a data structure is a data organization, and storage format that is usually chosen for efficient access to data. More precisely, a data structure is a collection of data values, the relationships among them, and the functions or operations that can be applied to the data, i.e., it is an algebraic structure about data.
Eiffel is an object-oriented programming language designed by Bertrand Meyer and Eiffel Software. Meyer conceived the language in 1985 with the goal of increasing the reliability of commercial software development; the first version becoming available in 1986. In 2005, Eiffel became an ISO-standardized language.
A hash function is any function that can be used to map data of arbitrary size to fixed-size values, though there are some hash functions that support variable length output. The values returned by a hash function are called hash values, hash codes, hash digests, digests, or simply hashes. The values are usually used to index a fixed-size table called a hash table. Use of a hash function to index a hash table is called hashing or scatter storage addressing.
In computing, a hash table is a data structure often used to implement the map abstract data type. A hash table uses a hash function to compute an index, also called a hash code, into an array of buckets or slots, from which the desired value can be found. During lookup, the key is hashed and the resulting hash indicates where the corresponding value is stored.
In computer science, a trie, also called digital tree or prefix tree, is a type of k-ary search tree, a tree data structure used for locating specific keys from within a set. These keys are most often strings, with links between nodes defined not by the entire key, but by individual characters. In order to access a key, the trie is traversed depth-first, following the links between nodes, which represent each character in the key.
In computing, Microsoft's ActiveX Data Objects (ADO) comprises a set of Component Object Model (COM) objects for accessing data sources. A part of MDAC, it provides a middleware layer between programming languages and OLE DB. ADO allows a developer to write programs that access data without knowing how the database is implemented; developers must be aware of the database for connection only. No knowledge of SQL is required to access a database when using ADO, although one can use ADO to execute SQL commands directly.
In computer science, an associative array, map, symbol table, or dictionary is an abstract data type that stores a collection of pairs, such that each possible key appears at most once in the collection. In mathematical terms, an associative array is a function with finite domain. It supports 'lookup', 'remove', and 'insert' operations.
In computer science, a perfect hash functionh for a set S is a hash function that maps distinct elements in S to a set of m integers, with no collisions. In mathematical terms, it is an injective function.
In computer programming, foreach loop is a control flow statement for traversing items in a collection. foreach is usually used in place of a standard for loop statement. Unlike other for loop constructs, however, foreach loops usually maintain no explicit counter: they essentially say "do this to everything in this set", rather than "do this x times". This avoids potential off-by-one errors and makes code simpler to read. In object-oriented languages, an iterator, even if implicit, is often used as the means of traversal.
An SQL INSERT statement adds one or more records to any single table in a relational database.
In the Perl programming language, autovivification is the automatic creation of new arrays and hashes as required every time an undefined value is dereferenced. Perl autovivification allows a programmer to refer to a structured variable, and arbitrary sub-elements of that structured variable, without expressly declaring the existence of the variable and its complete structure beforehand.
Linear probing is a scheme in computer programming for resolving collisions in hash tables, data structures for maintaining a collection of key–value pairs and looking up the value associated with a given key. It was invented in 1954 by Gene Amdahl, Elaine M. McGraw, and Arthur Samuel and first analyzed in 1963 by Donald Knuth.
In computing, sort is a standard command line program of Unix and Unix-like operating systems, that prints the lines of its input or concatenation of all files listed in its argument list in sorted order. Sorting is done based on one or more sort keys extracted from each line of input. By default, the entire input is taken as sort key. Blank space is the default field separator. The command supports a number of command-line options that can vary by implementation. For instance the "-r
" flag will reverse the sort order.
The Java collections framework is a set of classes and interfaces that implement commonly reusable collection data structures.
2-choice hashing, also known as 2-choice chaining, is "a variant of a hash table in which keys are added by hashing with two hash functions. The key is put in the array position with the fewer (colliding) keys. Some collision resolution scheme is needed, unless keys are kept in buckets. The average-case cost of a successful search is , where is the number of keys and is the size of the array. The most collisions is with high probability."
Password strength is a measure of the effectiveness of a password against guessing or brute-force attacks. In its usual form, it estimates how many trials an attacker who does not have direct access to the password would need, on average, to guess it correctly. The strength of a password is a function of length, complexity, and unpredictability.
The fat comma is a syntactic construction that appears in a position in a function call where a comma would usually appear. The original usage refers to the ")
letters:(
" construction in ALGOL 60. Newer usage refers to the "=>
" operator present in some programming languages. It is primarily associated with PHP, Ruby and Perl programming languages, which use it to declare hashes. Using a fat comma to bind key-value pairs in a hash, instead of using a comma, is considered an example of good idiomatic Perl. In CoffeeScript and TypeScript, the fat comma is used to declare a function that is bound to this
.
bcrypt is a password-hashing function designed by Niels Provos and David Mazières, based on the Blowfish cipher and presented at USENIX in 1999. Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.
In C++, associative containers are a group of class templates in the standard library of the C++ programming language that implement ordered associative arrays. Being templates, they can be used to store arbitrary elements, such as integers or custom classes. The following containers are defined in the current revision of the C++ standard: set
, map
, multiset
, multimap
. Each of these containers differ only on constraints placed on their elements.
SDS BASIC, also known as CP-V BASIC, Batch BASIC or Sigma BASIC depending on the version, is a BASIC programming language compiler for Scientific Data Systems's (SDS) Sigma series mainframe computers, originally released in 1967. Xerox purchased SDS in 1969 and began rebranding it as Xerox Data Systems, and finally just Xerox, at which time the language became known as Xerox BASIC.
hcreate()
, hdestroy()
and hsearch()