Comparison of programming languages (associative array)
This []Comparison of programming languages compares the features of associative array data structures or array-lookup processing for over 40 computer programming languages.
Language support
The following is a comparison of associative arrays in various programming languages.Awk
has built-in, language-level support for associative arrays.For example:
phonebook = "555-9999"
phonebook = "555-1212"
phonebook = "555-1337"
The following code loops through an associated array and prints its contents:
for
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:
END
C
There is no standard implementation of associative arrays in C, but a 3rd-party library, C Hash Table, with BSD license, is available.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.
Finally, the GLib library also supports associative arrays, along with many other advanced data types and is the recommended implementation of the GNU Project.
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 isSystem.Collections.Generic.Dictionary
, 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
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.Creation
The following demonstrates three means of populating a mutable dictionary:- the
Add
method, which adds a key and value and throws an exception if the key already exists in the dictionary; - assigning to the indexer, which overwrites any existing value, if present; and
- assigning to the backing property of the indexer, for which the indexer is syntactic sugar.
Dictionary
dic.Add;
dic = "555-1212";
// Not allowed in C#.
// dic.Item = "553-1337";
dic = "553-1337";
The dictionary can also be initialized during construction using a "collection initializer", which compiles to repeated calls to
Add
.var dic = new Dictionary
Access by key
Values are primarily retrieved using the indexer and theTryGetValue
method, which has an output parameter for the sought value and a Boolean return-value indicating whether the key was found.var sallyNumber = dic;
var sallyNumber = ? result : "n/a";
In this example, the
sallyNumber
value will now contain the string "555-9999"
.Enumeration
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 theKeyValuePair
type, although there is no guarantee of order. For a sorted dictionary, the programmer could choose to use a SortedDictionary
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
C++
has a form of associative array calledstd::map
. One could create a phone-book map with the following code in C++:- include
- include
- include
Or less efficiently, as this creates temporary
std::string
values:- include
- include
With the extension of initialization lists in C++11, entries can be added during a map's construction as shown below:
- include
- include
You can iterate through the list with the following code :
std::map
for, end = phone_book.end; curr != end; ++curr)
std::cout << curr->first << " = " << curr->second << std::endl;
The same task in C++11:
for
std::cout << curr.first << " = " << curr.second << std::endl;
Using the structured binding available in C++17:
for
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
, which has the algorithmic characteristics of a hash table. This is a common vendor extension to the Standard Template Library as well, usually called hash_map
, available from such implementations as SGI and STLPort.CFML
A structure in CFML is equivalent to an associative array:dynamicKeyName = "John Doe";
phoneBook = ;
writeOutput; // ???
writeDump; // entire struct
Cobra
Initializing an empty dictionary and adding items in Cobra:dic as Dictionary
dic.add
dic.add
dic.add
assert dic '555-9999'
Alternatively, a dictionary can be initialized with all items during construction:
dic =
The dictionary can be enumerated by a for-loop, but there is no guaranteed order:
for key, val in dic
print "'s phone number is "
D
offers direct support for associative arrays in the core language; such arrays are implemented as a chaining hash table with binary trees. The equivalent example would be:int main
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
A property can be removed as follows:
phone_book.remove;
Delphi
supports several standard containers, including TDictionaryuses
SysUtils,
Generics.Collections;
var
PhoneBook: TDictionary
Entry: TPair
begin
PhoneBook := TDictionary
PhoneBook.Add;
PhoneBook.Add;
PhoneBook.Add;
for Entry in PhoneBook do
Writeln;
end.
Versions of Delphi prior to 2009 do not offer direct support for associative arrays. However, associative arrays can be simulated using the TStrings class:
procedure TForm1.Button1Click;
var
DataField: TStrings;
i: Integer;
begin
DataField := TStringList.Create;
DataField.Values := '555-9999';
DataField.Values := '555-1212';
DataField.Values := '553-1337';
// access an entry and display it in a message box
ShowMessage;
// loop through the associative array
for i := 0 to DataField.Count - 1 do
begin
ShowMessage;
end;
DataField.Free;
end;
Erlang
offers many ways to represent mappings; two of the most common in the standard library are keylists and dictionaries.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 = .
Accessing an element of the keylist can be done with the
lists:keyfind/3
function:= lists:keyfind,
io:format.
Dictionaries are implemented in the
dict
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,
PhoneBook3 = dict:store,
PhoneBook = dict:store.
Such a serial initialization would be more idiomatically represented in Erlang with the appropriate function:
PhoneBook = dict:from_list.
The dictionary can be accessed using the
dict:find/2
function:= dict:find,
io:format.
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.[|F#]
Map<'Key,'Value>
At runtime, F# provides theCollections.Map<'Key,'Value>
type, which is an immutable AVL tree.Creation
The following example calls theMap
constructor, which operates on a list of tuples.let numbers =
|> Map
Access by key
Values can be looked up via one of theMap
members, such as its indexer or Item
property or the TryFind
function, which returns an option type with a value of Some
, 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.let sallyNumber = numbers.
// or
let sallyNumber = numbers.Item
let sallyNumber =
match numbers.TryFind with
| Some -> number
| None -> "n/a"
In both examples above, the
sallyNumber
value would contain the string "555-9999"
.Dictionary<'TKey,'TValue>
Because F# is a.NET language, it also has access to features of the.NET Framework, including theSystem.Collections.Generic.Dictionary<'TKey,'TValue>
type, 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.Creation
Thedict
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>
.let numbers =
|> 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.let numbers = System.Collections.Generic.Dictionary
numbers.Add
numbers. <- "555-1212"
numbers.Item <- "555-1337"
Access by key
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.let sallyNumber =
let mutable result = ""
if numbers.TryGetValue then result else "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:
let sallyNumber =
match numbers.TryGetValue with
| true, number -> number
| _ -> "n/a"
Enumeration
A dictionary or map can be enumerated usingSeq.map
.// loop through the collection and display each entry.
numbers |> Seq.map
FoxPro
implements mapping with the Collection Class.mapping = NEWOBJECT
mapping.Add && Add – key must be character
index = mapping.GetKey && returns the index value 1
object = mapping && returns "Daffodils"
object = mapping && returns "Daffodils"
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: mapvaluetype
Adding elements one at a time:
phone_book := make // make an empty map
phone_book = "555-9999"
phone_book = "555-1212"
phone_book = "553-1337"
A map literal:
phone_book := map string
Iterating through a map:
// over both keys and values
for key, value := range phone_book
// over just keys
for key := range phone_book
Haskell
The Haskell programming language provides only one kind of associative container – a list of pairs:m =
main = print
output:
Just "555-1212"
Note that the lookup function returns a "Maybe" value, which is "Nothing" if not found, or "Just 'result when found.
GHC, the most commonly used implementation of Haskell, provides two more types of associative containers. Other implementations might also provide these.
One is polymorphic functional maps :
import qualified Data.Map as M
m = M.insert "Sally Smart" "555-9999" M.empty
m' = M.insert "John Doe" "555-1212" m
m'' = M.insert "J. Random Hacker" "553-1337" m'
main = print
output:
Just "555-1212"
A specialized version for integer keys also exists as Data.IntMap.
Finally, a polymorphic hash table:
import qualified Data.HashTable as H
main = do m <- H.new H.hashString
H.insert m "Sally Smart" "555-9999"
H.insert m "John Doe" "555-1212"
H.insert m "J. Random Hacker" "553-1337"
foo <- H.lookup m "John Doe"
print foo
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.
Java
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
phoneBook.put;
phoneBook.put;
phoneBook.put;
The method is used to access a key; for example, the value of the expression
phoneBook.get
is "555-9999"
. This code uses a hash map to store the associative array, by calling the constructor of the class. However, since the code only uses methods common to the interface, a self-balancing binary tree could be used by calling the constructor of the class, 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 method. Since every class in Java inherits from, 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 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.equals
if a.equals, then a.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 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 interface; or a custom 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
is a prototype-based object-oriented language.Map and WeakMap
Modern JavaScript handles associative arrays, using 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.Creation
A map can be initialized with all items during construction:var phoneBook = new Map;
Alternatively, you can initialize an empty map and then add items:
var phoneBook = new Map;
phoneBook.set;
phoneBook.set;
phoneBook.set;
Access by key
Accessing an element of the map can be done with the "get" method:var sallyNumber = phoneBook.get;
In this example, the sallyNumber value will now contain the string "555-9999".
Enumeration
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
A key can be removed as follows:
phoneBook.delete;
Object
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, 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. 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
. For example:var myObject = ;
To prevent the lookup from using the prototype's properties, you can use Object.setPrototypeOf function:
Object.setPrototypeOf;
As of ECMAScript 5, the prototype can also be bypassed by using Object.create:
var myObject = Object.create;
Object.assign;
If the property name is a valid identifier, the quotes can be omitted, e.g.:
var myOtherObject =
Lookup is written using property-access notation, either square brackets, which always work, or dot notation, which only works for identifier keys:
myObject
myOtherObject.foo
You can also loop through all enumerable properties and associated values as follows :
for
Or :
for
A property can be removed as follows:
delete myObject;
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 // key is "1"; note that myObject myObject
myObject'a','b' // key is "a,b"
myObject // 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' 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 for more information on the issue.
Julia
In Julia, the following operations manage associative arrays.Declare dictionary:
phonebook = Dict
Access element:
phonebook
Add element:
phonebook = "555-2222"
Delete element:
delete!
Get keys and values as iterables:
keys
values
KornShell 93, and compliant shells
In KornShell 93, and compliant shells, the following operations can be used with associative arrays.Definition:
typeset -A phonebook; # ksh93
declare -A phonebook; # bash4
phonebook=;
Dereference:
$;
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.'
)
The syntax
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 principle, and hence prepends to the list head.)
)
This function can be construed as a accommodation for
cons
operations.;; The effect of
;;
;; is equivalent to
;;
)))
)
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.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 leds to a return of the NIL
value.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".
)
phone-book)
;; Finds the first entry whose key is neither "Sally Smart" nor "John Doe"
)
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.
The corresponding generalizations
rassoc-if
and rassoc-if-not
exist.;; Finds the first entry whose value is "555-9999".
)
phone-book)
;; Finds the first entry whose value is not "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".
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".
)
phone-book)
Iteration is accomplished with the aid of any function that expects a list.
;; Iterate via "map".
entry
))
phone-book)
;; Iterate via "dolist".
entry
))
These being structured lists, processing and transformation operations can be applied without constraints.
;; Return a vector of the "phone-book" values.
;; Destructively modify the "phone-book" via "map-into".
entry
)))
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.)
The
gethash
function permits obtaining the value associated with a key.Additionally, a default value for the case of an absent key may be specified.
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.))
Use
remhash
for deleting the entry associated with a key.clrhash
completely empties the hash table.The dedicated
maphash
function specializes in iterating hash tables.)
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.
do )
;; Iterate the values of the hash table.
A further option invokes
with-hash-table-iterator
, an iterator-creating macro, the processing of which is intended to be driven by the caller.))))
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
. Procedural code looks like:mapping phone_book = ;
phone_book = "555-9999";
phone_book = "555-1212";
phone_book = "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 would return the string "555-9999", and phone_book would return 0. Testing for presence is done using the function member, e.g.
if write;
Deletion is accomplished using a function called either m_delete or map_delete, depending on the driver:
m_delete;
LPC drivers of the Amylaar family implement multivalued mappings using a secondary, numeric index Example syntax:
mapping phone_book = ;
phone_book = "555-9999";
phone_book = "99 Sharp Way";
phone_book = "555-1212";
phone_book = "3 Nigma Drive";
phone_book = "555-1337";
phone_book = "77 Massachusetts Avenue";
LPC drivers modern enough to support a foreach construct use it to iterate through their mapping types.
Lua
In Lua, "table" is a fundamental type that can be used either as an array 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
. For example:phone_book =
aTable =
If the key is a valid identifier, 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:
x = aTable.subTable.k
You can also loop through all keys and associated values with iterators or for-loops:
simple =
function FormatElement
return " = ".. value.. ", "
end
-- Iterate on all keys
table.foreach
print""
for k, v in pairs do io.write end
print""
k= nil
repeat
k, v = next
if k ~= nil then io.write end
until k nil
print""
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
and Wolfram Language use the Association expression to represent associative arrays.phonebook = <| "Sally Smart" -> "555-9999",
"John Doe" -> "555-1212",
"J. Random Hacker" -> "553-1337" |>;
To access:
phonebookKey
If the keys are strings, the Key keyword is not necessary, so:
phonebook"Sally Smart"
To list keys: and values
Keys
Values
MUMPS
In MUMPS every array is an associative array. The built-in, language-level, direct support for associative arraysapplies 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="555-9999" ;; storing permanent data
SET phonebook="555-1212" ;; storing temporary data
SET phonebook="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,!
You can also loop through an associated array as follows:
SET NAME=""
FOR S NAME=$ORDER QUIT:NAME="" WRITE NAME," Phone Number :",^phonebook,!
Objective-C (Cocoa/GNUstep)
and GNUstep, written in Objective-C, handle associative arrays usingNSMutableDictionary
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.NSMutableDictionary *aDictionary = NSMutableDictionary alloc] init];
;
;
;
To access assigned objects, this command may be used:
id anObject = ;
All keys or values can be enumerated using
NSEnumerator
:NSEnumerator *keyEnumerator = ;
id key;
while )
In Mac OS X 10.5+ and iPhone OS, dictionary keys can be enumerated more concisely using the
NSFastEnumeration
construct: for
What is even more practical, structured data graphs may be easily created using Cocoa, especially
NSDictionary
. This can be illustrated with this compact example:NSDictionary *aDictionary =
, @"students",
, @"hackers",
nil];
Relevant fields can be quickly accessed using key paths:
id anObject = ;
OCaml
The OCaml programming language provides three different associative containers. The simplest is a list of pairs:- let m = ;;
;
;
- List.assoc "John Doe" m;;
The second is a polymorphic hash table:
- let m = Hashtbl.create 3;;
- Hashtbl.add m "Sally Smart" "555-9999";
Hashtbl.add m "J. Random Hacker" "553-1337";;
- : unit =
- Hashtbl.find m "John Doe";;
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 :
- module StringMap = Map.Make;;
- let m = StringMap.add "Sally Smart" "555-9999" StringMap.empty
let m = StringMap.add "J. Random Hacker" "553-1337" m;;
val m : string StringMap.t =
- StringMap.find "John Doe" m;;
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
, 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.
OptimJ
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 phoneBook = ;
// String is not a java type but an optimj type:
// associative array of strings indexed by strings.
// iterate over the values
for
// The previous statement prints: "555-9999" "555-1212" "553-1337"
// iterate over the keys
for
// phoneBook access a value by a key
// i.e. phoneBook 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 a;
java.util.Map
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 = ;
Accessing a hash element uses the syntax
$hash_name
– 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
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
One can iterate through pairs using the
each
function:while
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 = ;
Values in a hash reference are accessed using the dereferencing operator:
print $phone_book->;
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
Perl 6 (Raku)
, 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
– the key is surrounded by curly braces and the hash name. The value of %phone-book
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
By default, when iterating through a hash, one gets key–value pairs.
for %phone-book -> $entry
It is also possible to get alternating key values and value values by using the
kv
method:for %phone-book.kv -> $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.
sub list-phone-book
list-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.
- Keys must be integer numbers, as in this case.
- This will cause an error, as strings as keys are invalid.
PHP
's built-in array type is, in reality, an associative array. Even when using numerical indexes, PHP internally stores arrays as associative arrays. So, PHP can have non-consecutively numerically-indexed arrays. The keys have to be of 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 = '555-9999';
$phonebook = '555-1212';
$phonebook = '555-1337';
// or
$phonebook = array;
// or, as of PHP 5.4
$phonebook = ;
// or
$phonebook = '555-9999';
$phonebook = '555-1212';
$phonebook = '555-1337';
PHP can loop through an associative array as follows:
foreach
// For the last array example it is used like this
foreach
PHP has an extensive set of functions to operate on arrays.
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.Pike
has built-in support for associative arrays, which are referred to as mappings. Mappings are created as follows:mapping phonebook = ;
Accessing and testing for presence in mappings is done using the indexing operator. So
phonebook
would return the string "555-9999"
, and phonebook
would return 0.Iterating through a mapping can be done using
foreach
:foreach
Or using an iterator object:
Mapping.Iterator i = get_iterator;
while )
Elements of a mapping can be removed using
m_delete
, which returns the value of the removed index:string sallys_number = m_delete;
PostScript
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 declaration
3 dict dup begin
/red def
/green def
/blue def
end
% Level 2 declaration
<<
/red
/green
/blue
>>
% 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
/red get print % outputs 'rot'
begin
green print % outputs 'vert'
end
Dictionary contents can be iterated through using
forall
, though not in any particular order:% Level 2 example
<<
/This 1
/That 2
/Other 3
>> forall
Which may output:
That is 2
This is 1
Other is 3
Dictionaries can be augmented or altered using
put
, and entries can be removed using undef
:% define a dictionary for easy reuse:
/MyDict <<
/rouge
/vert
>> def
% add to it
MyDict /bleu put
% change it
MyDict /vert put
% remove something
MyDict /rouge undef
Prolog
Some versions of Prolog include dictionary utilities.Python
In Python, associative arrays are called "dictionaries". Dictionary literals are delimited by curly braces:phonebook =
To access an entry in Python simply use the array indexing operator:
>>> phonebook
'555-9999'
Loop iterating through all the keys of the dictionary:
>>> for key in phonebook:
Sally Smart 555-9999
J. Random Hacker 553-1337
John Doe 555-1212
Iterating through tuples:
>>> for key, value in phonebook.items:
Sally Smart 555-9999
J. Random Hacker 553-1337
John Doe 555-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:>>> del phonebook
>>> val = phonebook.pop
>>> phonebook.keys # Only one key left
Python 2.7 and 3.x also support dictionary list comprehension, a compact syntax for generating a dictionary from any iterator:
>>> square_dict =
>>> square_dict
>>>
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 =
The dictionary keys must be of an immutable data type. In Python, strings are immutable due to their method of implementation.
Red
In Red the built-inmap!
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
#
, or can be created using make map!
:Red
my-map: make map!
; Notice that the block is not reduced or evaluated in any way, therefore in the above example the key
bar
is associated with the word!
false
rather than the logic!
value false; literal syntax can be used if the latter is desired:my-other-map: make map!
my-other-map/bar: false
; Lookup can be written using
path!
notation or using the select
action:select my-map "Sally Smart"
my-other-map/foo
; You can also loop through all keys and values with
foreach
:foreach my-map
; A key can be removed using
remove/key
:remove/key my-map "Sally Smart"
REXX
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.
Ruby
In Ruby a hash table is used as follows:irb:001:0> phonebook =
=>
irb:006:0> phonebook
=> "555-1212"
Ruby supports hash looping and iteration with the following syntax:
irb:007:0> ### iterate over keys and values
irb:008:0* phonebook.each
Sally Smart => 555-9999
John Doe => 555-1212
J. Random Hacker => 553-1337
=>
irb:009:0> ### iterate keys only
irb:010:0* phonebook.each_key
Sally Smart
John Doe
J. Random Hacker
=>
irb:011:0> ### iterate values only
irb:012:0* phonebook.each_value
555-9999
555-1212
553-1337
=>
Ruby also supports many other useful operations on hashes, such as merging hashes, selecting or rejecting elements that meet some criteria, inverting, and flattening a hash into an array.
S-Lang
has an associative array type:phonebook = Assoc_Type;
phonebook = "555-9999"
phonebook = "555-1212"
phonebook = "555-1337"
You can also loop through an associated array in a number of ways:
foreach 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;
i = array_sort;
vals = assoc_get_values;
array_map ;
Scala
provides an immutableMap
class as part of the scala.collection
framework:val phonebook = Map
Scala's type inference will decide that this is a
Map
. To access the array:phonebook.get
This returns an
Option
type, Scala's equivalent of the Maybe monad in Haskell.Smalltalk
In Smalltalk aDictionary
is used:phonebook := Dictionary new.
phonebook at: 'Sally Smart' put: '555-9999'.
phonebook at: 'John Doe' put: '555-1212'.
phonebook at: 'J. Random Hacker' put: '553-1337'.
To access an entry the message
#at:
is sent to the dictionary object:phonebook at: '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 or keep weak references.
Because every object implements #hash, any object can be used as key.
SNOBOL
is one of the first programming languages to use associative arrays. Associative arrays in SNOBOL are called Tables.PHONEBOOK = TABLE
PHONEBOOK = '555-9999'
PHONEBOOK = '555-1212'
PHONEBOOK = '553-1337'
Standard ML
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 implementation provides a signature,
ORD_MAP
, which defines a common interface for ordered functional associative arrays. There are several general functors—BinaryMapFn
, ListMapFn
, RedBlackMapFn
, and SplayMapFn
—that allow you to create the corresponding type of ordered map 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
.- structure StringMap = BinaryMapFn ;
structure StringMap : ORD_MAP
- val m = StringMap.insert
val m = StringMap.insert
val m = StringMap.insert ;
val m =
T
: string StringMap.map
- StringMap.find ;
val it = SOME "555-1212" : string option
SML/NJ also provides a polymorphic hash table:
- exception NotFound;
exception NotFound
- val m : HashTable.hash_table = HashTable.mkTable ;
val m =
HT
: HashTable.hash_table
- HashTable.insert m ;
val it = : unit
- HashTable.insert m ;
val it = : unit
- HashTable.insert m ;
val it = : unit
HashTable.find m "John Doe";
val it = SOME "555-1212" : string option
- HashTable.lookup m "John Doe";
val it = "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.Tcl
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.array
set 555-9999
set john
set phonebook 555-1212
set 553-1337
If there is a space character in the variable name, the name must be grouped using either curly brackets or double quotes.
Alternatively, several array elements can be set by a single command, by presenting their mappings as a list :
array set phonebook
To access one array entry and put it to standard output:
puts $phonebook
Which returns this result:
555-9999
To retrieve the entire array as a dictionary:
array get phonebook
The result can be :
555-9999 553-1337 555-1212
dict
set phonebook
To look up an item:
dict get $phonebook
To iterate through a dict:
foreach $phonebook
Visual Basic
can use the Dictionary class from the Microsoft Scripting Runtime. There is no standard implementation common to all versions:' Requires a reference to SCRRUN.DLL in Project Properties
Dim phoneBook As New Dictionary
phoneBook.Add "Sally Smart", "555-9999"
phoneBook.Item = "555-1212"
phoneBook = "553-1337"
For Each name In phoneBook
MsgBox name & " = " & phoneBook
Next
Visual Basic .NET
uses the collection classes provided by the.NET Framework.Creation
The following code demonstrates the creation and population of a dictionary :Dim dic As New System.Collections.Generic.Dictionary
dic.Add
dic = "555-1212"
dic.Item = "553-1337"
An alternate syntax would be to use a collection initializer, which compiles down to individual calls to
Add
:Dim dic As New System.Collections.Dictionary From
Access by key
Example demonstrating access :Dim sallyNumber = dic
' or
Dim sallyNumber = dic.Item
Dim result As String = Nothing
Dim sallyNumber = If
Enumeration
Example demonstrating enumeration :' loop through the collection and display each entry.
For Each kvp As KeyValuePair In dic
Console.WriteLine
Next
Windows PowerShell
Unlike many other command line interpreters, Windows PowerShell has built-in, language-level support for defining associative arrays:$phonebook = @
As in JavaScript, if the property name is a valid identifier, the quotes can be omitted:
$myOtherObject = @
Entries can be separated by either a semicolon or a newline:
$myOtherObject = @
Keys and values can be any.NET object type:
$now = ::Now
$tomorrow = $now.AddDays
$ProcessDeletionSchedule = @
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 += @
$phonebook += @
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 = '555-9999'
$phonebook.'John Doe' = '555-1212'
$phonebook.Add
To dereference assigned objects, the array index operator, the property operator, or the parameterized property
Item
of the.NET object can be used:$phonebook
$phonebook.'John Doe'
$phonebook.Item
You can loop through an associative array as follows:
$phonebook.Keys | foreach
An entry can be removed using the
Remove
method of the underlying.NET object:$phonebook.Remove
Hash tables can be added:
$hash1 = @
$hash2 = @
$hash3 = $hash1 + $hash2
Data serialization formats support
Many data serialization formats also support associative arraysJSON
In JSON, associative arrays are also referred to as objects. Keys can only be strings.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-9999
John Doe: 555-1212
J. Random Hacker: 555-1337