Comparison of programming languages (mapping)

Comparison of programming languages (mapping)
Programming language comparisons
General comparison
Basic syntax
Basic instructions
Arrays
Associative arrays
String operations
String functions
List comprehension
Object-oriented programming
Object-oriented constructors
Database access
Database RDBMS

Evaluation strategy
List of "hello world" programs

ALGOL 58's influence on ALGOL 60
ALGOL 60: Comparisons with other languages
Comparison of ALGOL 68 and C++
ALGOL 68: Comparisons with other languages
Compatibility of C and C++
Comparison of Pascal and Borland Delphi
Comparison of Object Pascal and C
Comparison of Pascal and C
Comparison of Java and C++
Comparison of C# and Java
Comparison of C# and Visual Basic .NET
This box: view · talk · edit


Contents

Language support

The following is a comparison of associative arrays (also "mapping", "hash", and "dictionary") in various programming languages. For more details, see Associative array.

Awk

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"

You can also loop through an associated array as follows:

for (name in phonebook) {
        print name, " ", phonebook[name]
}

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
        multi[$1 SUBSEP $2]++;
}
#
END {
        for (x in multi) {
                split(x, arr, SUBSEP);
                print arr[1], arr[2], multi[x];
        }
}

Thompson AWK [1] provides built-in multi-dimensional associative arrays:

{ # for every input line
        multi[$1][$2]++;
}
#
END {
        for (x in multi)
                for (y in multi[x])
                print x, y, multi[x][y];
}

C

There is no standard implementation of an associative array in C, but a 3rd party library with BSD license is available here[dead link] . POSIX 1003.1-2001 describes the functions hcreate(), hdestroy() and hsearch().

Another 3rd party library, uthash, also creates associative arrays from C structures. A structure represents a value, and one of the structure fields acts 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[citation needed].

ColdFusion

You can use a ColdFusion structure to perform as an associative array. Here is a sample in ColdFusion:

<cfscript>
        phoneBook = StructNew();
        phoneBook["Sally Smart"] = "555-9999";
        phoneBook["John Doe"] = "555-1212";
        phoneBook["J. Random Hacker"] = "555-1337"; 
        phoneBook[sName] = "555-4321";
        phoneBook.UnknownComic = "???";
</cfscript>
 
<cfoutput>
<!-- will output 3 question marks below: -->
 
        #phoneBook["UnknownComic"]#
 
<!-- will dump the structure: --->
 
       <cfdump var = "#phonebook#" />
 
</cfoutput>

C#

Hashtable ht = new Hashtable();
ht.Add("testKey", "AssociatedData");
MessageBox.Show((string) ht["testKey"]);
Dictionary<int, string> dic = new Dictionary<int, string>();
dic.Add(7, "Bond");
MessageBox.Show(dic[7]);

In the above sample the Hashtable class is only capable of associating a String key with a value of Object type. Because in .NET all types (except pointers) ultimately derive from Object, anything can be put into a Hashtable, even data of different types. This could lead to errors if consuming code expects data to be of a singular type. In the above code casting is required to convert the Object variables back to their original type. Additionally, casting value-types (structures such as integers) to Object to put into the Hashtable and casting them back requires boxing/unboxing which incurs both a slight performance penalty and pollutes the heap with garbage. This changes in C# 2.0 with generic hashtables called dictionaries. There are significant performance and reliability gains to these strongly typed collections because they do not require boxing/unboxing or explicit type casts and introduce compile-time type checks. C# 3.0 adds a shorthand notation for the dictionary initialization:

Dictionary<int, string> = new Dictionary<int, string> {
    { 7, "Bond" }
};

C++

C++ also has a form of associative array called 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 <map>
#include <string>
 
int main() {
        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";
        return 0;
}

You can iterate through the list with the following code:

std::map<std::string, std::string>::iterator curr,end;
for(curr = phone_book.begin(), end = phone_book.end();  curr != end;  curr++)
        std::cout <<  curr->first << " = " << curr->second << 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++'s Technical Report 1 (TR1) defines a second map called std::tr1::unordered map with the algorithmic characteristics of a hash table. This is a common vendor extension to the STL as well, usually called hash_map, being available from such implementations as SGI and STLPort.

Cocoa/GNUstep (Objective-C)

Cocoa (API) and GNUstep handle associative arrays using NSMutableDictionary (a mutable version of NSDictionary) class cluster. This class allows assignments between any two objects to be made. 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 (both explicitly or by adding to the dictionary a different object with the same key).

NSMutableDictionary *aDictionary = [[NSMutableDictionary alloc] init];
[aDictionary setObject:@"555-9999" forKey:@"Sally Smart"]; 
[aDictionary setObject:@"555-1212" forKey:@"John Doe"]; 
[aDictionary setObject:@"553-1337" forKey:@"Random Hacker"];

To access assigned objects this command may be used:

id anObject = [aDictionary objectForKey:@"Sally Smart"];

All keys or values can be simply enumerated using NSEnumerator

NSEnumerator *keyEnumerator = [aDictionary keyEnumerator];
id key;
while ((key = [keyEnumerator nextObject]))
{
  // ... process it here ...
}

On Mac OS X 10.5+ and iPhone OS, dictionary keys can also be enumerated more concisely using this NSFastEnumeration construct:

for (id key in aDictionary) {
  // ... 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 =
       [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 = [aDictionary valueForKeyPath:@"students.Sally Smart"];

D

D offers direct support for associative arrays in the core language – they are implemented as a chaining hash table with binary trees.[1] The equivalent example would be:

int main() {
        string[ string ] phone_book;
        phone_book["Sally Smart"] = "555-9999";
        phone_book["John Doe"] = "555-1212";
        phone_book["J. Random 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.

You can also loop through all properties and associated values, i.e. 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

Versions of Delphi prior to 2009 do not offer direct support for associative arrays. However, you can simulate associative arrays using TStrings object. Here's an example:

procedure TForm1.Button1Click(Sender: TObject);
var
  DataField: TStrings;
  i: Integer;
begin
  DataField := 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 box
  ShowMessage(DataField.Values['Sally Smart']);
 
  // loop through the associative array 
  for i := 0 to DataField.Count - 1 do
  begin
    ShowMessage('Number for ' + DataField.Names[i] + ': ' + DataField.ValueFromIndex[i]);
  end;
 
  DataField.Free;
end;

Delphi 2009 introduced support for generics as well as several standard generic containers, including TDictionary.

uses
  SysUtils,
  Generics.Collections;
 
var
  PhoneBook: TDictionary<string, string>;
  Entry: TPair<string, string>;
 
begin
  PhoneBook := TDictionary<string, string>.Create;
  PhoneBook.Add('Sally Smart', '555-9999');
  PhoneBook.Add('John Doe', '555-1212');
  PhoneBook.Add('J. Random Hacker', '553-1337');
 
  for Entry in PhoneBook do
    Writeln(Format('Number for %s: %s',[Entry.Key, Entry.Value]));
end.

Erlang

Erlang offers many approaches 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 = [{"Sally Smart", "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 Smart", 1, PhoneBook),
io:format("Phone number: ~s~n", [Phone]).

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("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.

FoxPro

Visual FoxPro implements mapping with the Collection Class.

mapping = NEWOBJECT("Collection")
mapping.Add("Daffodils", "flower2") && Add(object, key) – key must be character
index   = mapping.GetKey("flower2") && returns the index value 1
object  = mapping("flower2")        && returns "Daffodils" (retrieve by key)
object  = mapping(1)                && returns "Daffodils" (retrieve by index)

GetKey returns 0 if the key is not found.

See Collection in FoxPro Help for all the details.

Go

Go has built-in, language-level support for associative arrays, called maps. A map's key type may only be a boolean, numeric, string, pointer, function, interface, map, or channel type. A map type is written like this: map[keytype]valuetype.

Adding elements one at a time:

phone_book := make(map[string] string) // make an empty map
phone_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 over a map:

// over both keys and values
for key, value := range phone_book {
        fmt.Printf("Number for %s: %s\n", key, value)
}

// over just keys
for key := range phone_book {
        fmt.Printf("Name: %s\n", key)
}

Haskell

The Haskell programming language's report only provides 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.

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 (represented as immutable balanced binary trees):

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 (M.lookup "John Doe" m'' :: Maybe String)

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"; they 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 mapping strings to strings might be specified as follows:

Map<String, String> phoneBook = new HashMap<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 above 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, one could also use a self-balancing binary tree 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 use a number of other underlying data structures that implement the Map interface.

The hash function in Java, used by HashMap and HashSet, is provided by the method Object.hashCode(). 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 based on the properties of the object.

The Object class also contains the method equals(Object) that tests the 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)
    
  • if a.equals(b), then a.hashCode() == b.hashCode()
    

In order to maintain this contract, a class that overrides equals() must also override hashCode(), and maybe vice versa, so that hashCode() is based on the same properties (or a subset of the properties) as equals().

A further contract that hashed data structures 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, requires 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. Like with HashMap above, the relative ordering of keys in a TreeMap should not change once they have been inserted into the map.

JavaScript

JavaScript (and its standardized version: ECMAScript) is a prototype-based object-oriented language. In JavaScript an object is a mapping from property names to values—that is, an associative array with one caveat: since property names are strings, only string and (coerced) integer keys are allowed. Other than that difference, objects also include one feature unrelated to associative arrays: a prototype link to the object they inherit from. Doing a lookup for a property will forward the lookup to the prototype if the object does not define the property itself.

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:

myObject["John Doe"]
myOtherObject.foo

You can also loop through all enumerable properties and associated values as follows:

for(var property in myObject) {
        var value = myObject[property];
        alert("myObject[" + property + "] = " + value);
}

A property can be removed as follows:

delete myObject["Sally Smart"];

As mentioned before, properties are strings. However, 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:function(){return 'hello world';}}] // key is "hello world"

Any object, including built-in objects such as Array, can be dynamically extended with new properties. For example:

Array.prototype.removeAllObjects = function () {
        /* ... */
}

In modern JavaScript it's considered bad form to use the Array type as an associative array. Consensus is that the Object type is best for this purpose. The reasoning behind this is that if Array is extended via prototype and Object is kept pristine, 'for(in)' loops will work as expected on associative 'arrays'. This issue has been drawn into focus by the popularity of JavaScript frameworks that make heavy and sometimes indiscriminate use of prototype to extend JavaScript's inbuilt types.

See JavaScript Array And Object Prototype Awareness Day for more information on the issue.

KornShell 93 (and compliant shells: ksh93, zsh, bash4...)

Definition:

typeset -A phonebook; # ksh93
declare -A phonebook; # bash4
phonebook=(["Sally Smart"]="555-9999" ["John Doe"]="555-1212" ["J. Random Hacker"]="555-1337");

Dereference:

${phonebook["John Doe"]};

Lisp

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 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 structures and/or the object-oriented programming features, in conjunction with lists, arrays, and hash tables.

LPC

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 use looks like:

mapping phone_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, used like: m_delete(phone_book, "Sally Smart");

LPC drivers of the "Amylaar" family implement multivalued mappings using a secondary, numeric index. (Drivers of the MudOS family do not support multivalued mappings.) Example syntax:

mapping phone_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 allow iteration over their mapping types using it.

Lua

In Lua, table is a fundamental type that can be used either as array (numerical index, fast) or as 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 value
        subTable = { 5, 7.5, k = true }, – key is "subTable"
        -- Function as value
        ['John Doe'] = function (age) if age < 18 then return "Young" else return "Old!" end end,
        -- Table and function (and other types) can also be used as keys
}

If the key is a valid identifier (not a keyword), the quotes can be omitted. They 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 }
function FormatElement(key, value)
        return "[" .. tostring(key) .. "] = " .. value .. ", "
end
-- Iterate on all keys
table.foreach(simple, function (k, v) io.write(FormatElement(k, v)) end)
print""
for k, v in pairs(simple) do io.write(FormatElement(k, v)) end
print""
k= nil
repeat
        k, v = next(simple, k)
        if k ~= nil then io.write(FormatElement(k, v)) 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

MUMPS

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 arrays stored on disk which are available concurrently by multiple jobs. The name for globals is preceded by the circumflex "^" to distinguish it from local variable names.

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),!

OCaml

The OCaml programming language provides three different associative containers. The simplest is a list of pairs:

# 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 = <abstr>
# Hashtbl.add m "Sally Smart" "555-9999";
  Hashtbl.add m "John Doe" "555-1212";
  Hashtbl.add m "J. Random Hacker" "553-1337";;
- : unit = ()
# Hashtbl.find m "John Doe";;
- : string = "555-1212"

The code above uses OCaml's default hash function Hashtbl.hash, which is defined automatically for all types. If you wanted to use your own hash function, you can use the functor interface Hashtbl.Make to create a module, like with Map below.

Finally, functional maps (represented as immutable balanced binary trees):

# module StringMap = Map.Make(String);;
...
# let m = StringMap.add "Sally Smart" "555-9999" StringMap.empty
  let m = StringMap.add "John Doe" "555-1212" m
  let m = StringMap.add "J. Random Hacker" "553-1337" m;;
val m : string StringMap.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, where you provide the comparison function when creating the map.

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.

Optimj

The OptimJ programming language is an extension of Java 5. As java, Optimj provides maps. But, OptimJ also provides true associative arrays: java arrays are indexed with 0-based integers; associative arrays are indexed with any collection of keys.

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 values
for(String number : phoneBook) {
System.out.println(number);
}
 
// The previous statement prints:  "555-9999" "555-1212" "553-1337"
 
// iterate over the keys
for(String name : 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 array and associative arrays, to mix maps and associative arrays.

 int[String][][double] a;
 java.util.Map<String[Object], Integer> b;

Perl

Perl has built-in, language-level support for associative arrays. Modern Perl vernacular refers to associative arrays as hashes; the term associative array is found in older documentation, but is considered somewhat archaic. Perl hashes are flat: keys are strings and values are scalars. However, values may be references to arrays or other hashes, and the standard Perl 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 mostly semantically identical to the comma and makes the key-value association clearer:

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

$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";
}

PHP

PHP's built-in array type is in reality an associative array. Even when using numerical indexes, PHP internally stores it as an associative array.[2] This is why one in PHP can have non-consecutive numerically indexed arrays. The keys have to be integer or string (floating point numbers are truncated to integer), 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
$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 ($phonebook as $name => $number) {
        echo "Number for $name: $number\n";
}
 
// For the last array example it is used like this
foreach($phonebook['contacts'] as $name => $num)
{
   echo "<div>Name:{$name}</div>";
   echo "<div>Number:{$num['number']}</div>";
}

PHP has an extensive set of functions to operate on arrays.

If you want an associative array that can use objects as keys instead of strings and integers, you can use the SplObjectStorage class from the Standard PHP Library (SPL).

Pike

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 either foreach:

foreach(phonebook; string key; string value) {
        write("%s:%s\n", key, value);
}

Or using an iterator object:

Mapping.Iterator i = 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:

string sallys_number = m_delete(phonebook, "Sally Smart");

PostScript

In PostScript, associative arrays are called dictionaries. In Level 1 PostScript they must be created explicitly, but Level 2 introduced direct declaration using the double-brace syntax:

 % Level 1 declaration
 3 dict dup begin
   /red   (rouge) def
   /green (vert)  def
   /blue  (bleu)  def
 end

 % 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
 /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
 >> {exch =print ( is ) print ==} forall

May well output:

 That is 2
 This is 1
 Other is 3

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 it
 MyDict /bleu (blue) put

 % change it
 MyDict /vert (green) put

 % remove something
 MyDict /rouge undef

Python

In Python, associative arrays are called dictionaries. Dictionary literals are marked with curly braces:

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 phonebook['Sally Smart'] would return '555-9999'.

An example loop iterating through all the keys of the dictionary:

for key in phonebook:
        print key, phonebook[key]

Iterating through (key, value) tuples:

for key, value in phonebook.items():
        print key, value

Dictionaries can also be constructed with the dict builtin, which is most commonly found inside list comprehensions and generator expressions, and it takes a key-value list:

dict((key, value) for key, value in phonebook.items() if 'J' in key)

Dictionary keys can be individually deleted using the del statement. The corresponding value can be returned before the key-value pair are deleted using the pop method of dict types:

del phonebook['John Doe']
val = phonebook.pop('Sally Smart')
assert phonebook.keys() == ['J. Random Hacker'] # Only one key left

Python 3.0 also supports dictionary comprehensions, a compact syntax for generating a dictionary from any iterator:

square_dict={i:i*i for i in range(5)}
assert square_dict == {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

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. Ramdon Hacker'
PHONEBOOK.KEY = '553-1337'

Stem variables with numeric keys typically start at 1 and go up from there. The 0 key stem variable is used (by convention) as the count of items in the whole 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 for a stem variable and typically the keys are stored in a separate associative array with numeric keys.

Ruby

In Ruby a hash is used as follows:

phonebook = {
        'Sally Smart' => '555-9999', 
        'John Doe' => '555-1212', 
        'J. Random Hacker' => '553-1337'
}
 
phonebook['John Doe']; #produces this -> '555-1212'

Ruby supports hash looping and iteration with the following syntax:

### iterate over keys and values
phonebook.each {|key, value| puts key + " => " + value}
 
### iterate keys only
phonebook.each_key {|key| puts key}
 
### iterate values only
phonebook.each_value {|value| puts value}

S-Lang

S-Lang has an associative array type.

For example:

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. Here is one

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

Scala provides a immutable Map class as part of the scala.collection framework:

val phonebook = Map("Sally Smart" -> "555-9999",
  "John Doe" -> "555-1212",
  "J. Random Hacker" -> "553-1337")

Scala's type inference will work out that this is a Map[String, String]. To access the array:

phonebook.get("Sally Smart")

This returns an Option type, Scala's equivalent of a the Maybe monad in Haskell.

Smalltalk

In Smalltalk a dictionary 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'

gives

 '555-9999'

SNOBOL

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'

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 (kind of 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 that follows the ORD_MAP interface. In addition, there are two pre-defined modules for associative arrays with integer keys: IntBinaryMap and IntListMap.

- structure StringMap = BinaryMapFn (struct
                                       type ord_key = string
                                       val compare = String.compare
                                     end);
structure StringMap : ORD_MAP

- val m = StringMap.insert (StringMap.empty, "Sally Smart", "555-9999")
  val m = StringMap.insert (m, "John Doe", "555-1212")
  val m = StringMap.insert (m, "J. Random Hacker", "553-1337");
val m =
  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"} : string StringMap.map
- StringMap.find (m, "John Doe");
val it = SOME "555-1212" : string option

SML/NJ also provides a polymorphic hash table:

- exception NotFound;
exception NotFound
- val m : (string, string) HashTable.hash_table = HashTable.mkTable (HashString.hashString, op=) (3, NotFound);
val m =
  HT
    {eq_pred=fn,hash_fn=fn,n_items=ref 0,not_found=NotFound(-),
     table=ref [|NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,NIL,...|]}
  : (string,string) HashTable.hash_table
- HashTable.insert m ("Sally Smart", "555-9999");
val it = () : unit
- HashTable.insert m ("John Doe", "555-1212");
val it = () : unit
- HashTable.insert m ("J. Random Hacker", "553-1337");
val it = () : unit
HashTable.find m "John Doe"; (* returns NONE if not found *)
val it = SOME "555-1212" : string option
- HashTable.lookup m "John Doe"; (* raises the exception if not found *)
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

In Tcl every array is an associative array. As of Tcl 8.5, there is also the dict command that operates on dictionary values; arrays are always variables.

set "phonebook(Sally Smart)" 555-9999
set john "John Doe"
set phonebook($john) 555-1212
set "phonebook(J. Random Hacker)" 553-1337

The first argument of the set command has to be enclosed by double quotes when it contains an explicit space (even if the space is enclosed in an array parenthesis), because space is used to separate arguments in Tcl. This is not an issue with spaces inserted by substitution however, as the space in $john.

Alternatively, several array elements can be set in a single command by providing their mappings as a dictionary (keys braced because they contain whitespace):

array set phonebook {
        {Sally Smart} 555-9999
        {John Doe} 555-1212
        {J. Random Hacker} 553-1337
}

To access one array entry and put it on standard output

puts "$phonebook(Sally Smart)"

The result is here

555-9999

To retrieve the entire array as a dictionary:

array get phonebook

The result can be (order of keys is unspecified):

{Sally Smart} 555-9999 {J. Random Hacker} 553-1337 {John Doe} 555-1212

Visual Basic

There is no standard implementation common to all dialects. Visual Basic can use the Dictionary class from the Microsoft Scripting Runtime (which is shipped with Visual Basic 6):

' Requires a reference to SCRRUN.DLL in Project Properties
Dim phoneBook As New Dictionary
phoneBook.Add "Sally Smart", "555-9999"
phoneBook.Item("John Doe") = "555-1212"
phoneBook("J. Random Hacker") = "553-1337"
For Each name In phoneBook
        MsgBox name & " = " & phoneBook(name)
Next

Visual Basic .NET relies on the collection classes provided by .NET Framework:

Dim phoneBook As New System.Collections.Generic.Dictionary(Of String, String)
phoneBook("Sally Smart") = "555-9999"
phoneBook("John Doe") = "555-1212"
phoneBook("J. Random Hacker") = "553-1337"
For Each entry As KeyValuePair(Of String, String) In phoneBook
        MessageBox.Show(entry.Key & " = " & entry.Value)
Next

Windows PowerShell

Unlike many other command line interpreters, PowerShell has built-in, language-level support for defining associative arrays.

For example:

$phonebook = @{
        'Sally Smart' = '555-9999';
        'John Doe' = '555-1212'; 
        'J. Random Hacker' = '553-1337'
}

Like in JavaScript, if the property name is a valid identifier, the quotes can be omitted, e.g.:

$myOtherObject = @{ foo = 42; bar = $false }

Entries can be separated by either a semicolon or a newline, e.g.:

$myOtherObject = @{ foo = 42
                    bar = $false ;
                    zaz = 3
}

Keys and values can be any .NET object type, e.g.:

$now = [DateTime]::Now
$tomorrow = $now.AddDays(1)
$ProcessDeletionSchedule = @{ 
        (Get-Process notepad) = $now 
        (Get-Process calc) = $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, e.g.:

$hash1 = @{ a=1; b=2 }
$hash2 = @{ c=3; d=4 }
$hash3 = $hash1 + $hash2

Data serialization formats support

Many data serialization formats also support associative arrays (see this table)

JSON

Keys can only be strings

{
    "Sally Smart": "555-9999",
    "John Doe": "555-1212",
    "J. Random Hacker": "555-1337"
}

YAML

Sally Smart: 555-9999
John Doe: 555-1212
J. Random Hacker: 555-1337

References

  1. ^ "Associative Arrays". http://digitalmars.com/d/2.0/hash-map.html. Retrieved 2011-02-01. 
  2. ^ About the implementation of Arrays in PHP

Wikimedia Foundation. 2010.

Игры ⚽ Поможем сделать НИР

Look at other dictionaries:

  • Comparison of database access — Programming language comparisons General comparison Basic syntax Basic instructions Arrays Associative arrays String operations …   Wikipedia

  • Comparison of Java and C++ — Programming language comparisons General comparison Basic syntax Basic instructions Arrays Associative arrays String operations …   Wikipedia

  • Object-oriented programming — Programming paradigms Agent oriented Automata based Component based Flow based Pipelined Concatenative Concurrent computing …   Wikipedia

  • Mapping of Unicode characters — Unicode’s Universal Character Set has a potential capacity to support over 1 million characters. Each UCS character is mapped to a code point which is an integer between 0 and 1,114,111 used to represent each character within the internal logic… …   Wikipedia

  • Programming tool — A programming tool or software development tool is a program or application that software developers use to create, debug, maintain, or otherwise support other programs and applications. The term usually refers to relatively simple programs that… …   Wikipedia

  • Comparison of server-side JavaScript solutions — This is a list of Server side JavaScript solutions. Contents 1 Server side JavaScript use 2 See also 3 External links 4 References …   Wikipedia

  • Ada (programming language) — For other uses of Ada or ADA, see Ada (disambiguation). Ada Paradigm(s) Multi paradigm Appeared in 1980 Designed by MIL STD 1815/Ada 83: Jean Ichbiah Ada 95: Tucker Taft Ada 2005: Tucker Taft Stable release …   Wikipedia

  • Comparison of data serialization formats — This is a comparison of data serialization formats, different ways to convert complex objects to sequences of bits. It does not include markup languages used exclusively as document file formats. Contents 1 Overview 2 Syntax comparison of human… …   Wikipedia

  • Persistent programming language — Programming languages that natively and seamlessly allow objects to continue existing after the program has been closed down are called persistent programming languages. The only commercial product that appears to do this at the moment is JADE,… …   Wikipedia

  • Object-relational mapping — For another use of ORM , see Object role modeling. Object relational mapping (ORM, O/RM, and O/R mapping) in computer software is a programming technique for converting data between incompatible type systems in object oriented programming… …   Wikipedia

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”