An associative array (also map, hash, dictionary, finite map, lookup table, and in query-processing an index or index file) is an abstract data type composed of a collection of keys and a collection of values, where each key is associated with one value. The operation of finding the value associated with a key is called a lookup or indexing, and this is the most important operation supported by an associative array. The relationship between a key and its value is sometimes called a mapping or binding. For example, if the value associated with the key "bob" is 7, we say that our array maps "bob" to 7. Associative arrays are very closely related to the mathematical concept of a function with a finite domain. As a consequence, a common and important use of associative arrays is in memoization.
From the perspective of a programmer using an associative array, it can be viewed as a generalization of an array: While a regular array maps integers to arbitrarily typed objects (integers, strings, pointers, and, in an OO sense, objects), an associative array maps arbitrarily typed objects to arbitrarily typed objects. (Implementations of the two data structures, though, may be considerably different.)
The operations that are usually defined for an associative array are:
One can think of a telephone book as an example of an associative array, where names are the keys and phone numbers are the values. Another example would be a dictionary where words are the keys and definitions are the values. A database is a sort of generalized associative array.
Strong advantages of association lists include:
String-keyed maps can avoid extra comparisons during lookups by using tries.
In the scripting language Lua, associative arrays, called tables, are used as the primitive building block for all data structures, even arrays. Likewise, in JavaScript, all objects are associative arrays. In MUMPS, the associative arrays are typically stored as B-trees.
Associative arrays can be implemented in any programming language, and one or more implementations of them is typically found either built into the language or the standard library distributed with it (C is a notable exception, as neither the language nor the standard library directly provide one).
For example:
phonebookSmart" = "555-9999" phonebookDoe" = "555-1212" phonebookDoe" = "555-1337"
You can also loop through an associated array as follows:
for (name in phonebook) { print name, " ", phonebook* }
You can also check if an element is in the associative array, and delete elements from an associative array.
Multi-dimensional associative arrays can be implemented in standard Awk using concatenation and e.g. SUBSEP:
{ # for every input line multiSUBSEP $2++; } # END { for (x in multi) { split(x, arr, SUBSEP); print arrarr*; } }
Thompson AWK * provides built-in multi-dimensional associative arrays:
{ # for every input line multi**++; } # END { for (x in multi) for (y in multi*) print x, y, multi**; }
Hashtable ht = new Hashtable(); ht.Add("testKey", "AssociatedData"); MessageBox.Show(ht*);
another example:
Hashtable ht = new Hashtable(); ht* = "AssociatedData"; MessageBox.Show(ht*);
std::map (see Standard Template Library#Containers). One could create a map with the same information as above using C++ with the following code:
#include
In C++, the std::map class is templated which allows keys and values to be different data types. 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, the SGI STL also provides a std::hash_map which has the algorithmic benefits of a hash table.
NSMutableDictionary *aDictionary = alloc init" target="_blank" >*; setObject:@"555-9999" forKey:@"Sally Smart"; setObject:@"555-1212" forKey:@"John Doe"; setObject:@"553-1337" forKey:@"Random Hacker";
To access assigned objects this command may be used:
id anObject = objectForKey:@"Sally Smart";
All keys or values can be simply enumerated using NSEnumerator
NSEnumerator *keyEnumerator = allKeys objectEnumerator" target="_blank" >*; id *key; while (( key = nextObject )) { // ... process it here ... }
What is even more practical, structured data graphs may be easily created using Cocoa (API), especially NSDictionary (NSMutableDictionary). This can be ilustrated with this compact example:
NSDictionary *aDictionary = [NSDictionary dictionaryWithObjectsAndKeys: [NSDictionary dictionaryWithObjectsAndKeys: @"555-9999", @"Sally Smart", @"555-1212", @"John Doe", nil], @"students", [NSDictionary dictionaryWithObjectsAndKeys: @"553-1337", @"Random Hacker", nil], @"hackers", nil];
And relevant fields can be quickly accessed using key paths:
id *anObject = valueForKeyPath:@"students.Sally Smart";
int main() { char**] phone_book; phone_bookSmart" = "555-9999"; phone_bookDoe" = "555-1212"; phone_bookRandom Hacker" = "553-1337"; return 0; }
Keys and values can be any types, but all the keys in an associative array must be of the same type, and the same for values.
Map
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 class; however, since the code only uses methods common to the interface , one could also use a self-balancing binary tree by calling the constructor of the class, without changing the definition of the phone_book variable or the rest of the code, or use a number of other underlying data structures that implement the Map interface.
The hash function in Java 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 based on the properties of the object.
The Object class also contains the method that tests the object for equality with another object. Maps in Java rely on objects maintaining the following contract between their hashCode() and equals() methods:
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 the map 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.
An object literal is written as { property1 : value1, property2 : value2, ... }. For example:
var 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.:
var myOtherObject = { foo : 42, bar : false }
Lookup is written using property access notation, either square brackets, which always works, or dot notation, which only works for identifier keys:
myObjectDoe" myOtherObject.foo
Any object, including built-in objects such as Array, can be dynamically extended with new properties. For example:
Array.prototype.removeAllObjects = function () { /* ... */ }
'(("Sally Smart" . "555-9999") ("John Doe" . "555-1212") ("J. Random Hacker" . "553-1337"))
The syntax (x . y) is used to indicate a consed 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.
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.
It is easy to construct composite abstract data types in Lisp, using the object-oriented programming features in conjunction with lists, arrays, and hash tables.
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
To access 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),!
# let m = ["Sally Smart", "555-9999"; "John Doe", "555-1212"; "J. Random Hacker", "553-1337"];; val m : (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:
# let m = Hashtbl.create 3;;
val m : ('_a, '_b) Hashtbl.t =
Finally, functional maps (represented as immutable balanced binary trees):
# include (Map.Make(String));;
...
# let m = add "Sally Smart" "555-9999" empty
let m = add "John Doe" "555-1212" m
let m = add "J. Random Hacker" "553-1337" m;;
val m : string t =
Lists of pairs and functional maps both provide a purely functional interface. In contrast, hash tables provide an imperative interface. For many operations, hash tables are significantly faster than lists of pairs and functional maps.
A hash variable is marked by a % sigil, to distinguish it from scalar, array and other data types. A hash can be initialized from a key-value list:
%phone_book = ("Sally Smart", "555-9999", "John Doe", "555-1212", "J. Random Hacker", "553-1337");
Perl offers the => syntax, semantically (almost) equivalent to the comma, to make the key-value association more visible:
%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.
$phonebook = array () ; $phonebookSmart' = '555-9999' ; $phonebookDoe' = '555-1212' ; $phonebookRandom Hacker' = '555-1337' ;
$phonebook = array ( 'Sally Smart' => '555-9999', 'John Doe' => '555-1212', 'J. Random Hacker' => '555-1337' ) ;
You can also loop through an associative array as follows:
foreach ($phonebook as $name => $number) { echo "Number for $name: $number\n"; }
phonebook = {'Sally Smart' : '555-9999', 'John Doe' : '555-1212', 'J. Random Hacker' : '553-1337'}
To access an entry in python simply use the array indexing operator. For example, the expression phonebookSmart' would return '555-9999'.
An example loop iterating through all the keys of the dictionary:
for key in phonebook: print key, phonebook*
Iterating through (key, value) tuples:
for key, value in phonebook.iteritems(): print key, value
Dictionaries can also be constructed with the dict builtin, which takes a key-value list:
dict((key, value) for key, value in phonebook.items() if 'J' in key)
phonebook = { 'Sally Smart' => '555-9999', 'John Doe' => '555-1212', 'J. Random Hacker' => '553-1337' }
phonebookDoe' produces '555-1212'
To iterate over the hash, use something like the following:
phonebook.each {|key, value| puts key + " => " + value}
Additionally, each key may be shown individually:
phonebook.each_key {|key| puts key}
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'
gives
'555-9999'
set "phonebook(Sally Smart)" 555-9999 set "phonebook(John Doe)" 555-1212 set "phonebook(J. Random Hacker)" 553-1337
The first argument of the set command has to be enclosed by double quotes, as it contains a space. In Tcl, space is used to separate arguments. Alternatively, array setting can be grouped into a single command (keys braced because they contain whitespace):
array set phonebook { {Sally Smart} 555-9999 {John Doe} 555-1212 {J. Random Hacker} 553-1337 }
To access an entry and put it on standard output
puts "$phonebook(Sally Smart)"
The result is here
555-9999
Asociativní pole | Assoziatives Array | 連想配列 | Associatieve array | Tablica asocjacyjna | Ассоциативный массив
This article is licensed under the GNU Free Documentation License.
It uses material from the
"Associative array".
Home Page • arts • business • computers • games • health • hospitals • home • kids & teens • news • physicians • recreation• reference • regional • science • shopping • society • sports • world