Salvatore Mangano implements a dictionary data structure in his Mathematica Cookbook (ISBN: 978-0-596-52099-1, Copyright 2010 O'Reilly Media, Inc.). According to the copyright, I can share it with you ("answering a question by citing this book and quoting example code," as I am). For the same reasons as Halirutan mentions, more or less, he uses DownValues
and relies on it, but as he says, you need more functionality to be able to work with the dictionary data structure efficiently. His functions are surely only meant to be a start, many other languages implement many more such functions. But his is a start to see how it can be done and to build on. I put them into a package. The usage messages are mine, but the code has only been touched to fix what I assume were type setting errors in the book:
BeginPackage["DataDictionary`"]
makeDictionary::usage =
"makeDictionary[] initializes a new dictionary and returns an identifier.";
destroyDictionary::usage =
"destroyDictionary[dictionary] destroys a dictionary.";
dictName::usage =
"dictName[dictionary] returns the internal symbol used for storing data in a dictionary.";
dictStore::usage =
"dictStore[dictionary, key, value] stores a value in a dictionary using a key.";
dictReplace::usage =
"dictReplace[dictionary, key, value] works the same way as dictStore except that any duplicates in a dictionary will be removed.";
dictRemove::usage =
"dictRemove[dictionary, key, value] removes a value that is stored in a dictionary under a key.";
dictLookup::usage =
"dictLookup[dictionary, key] returns all values in a dictionary under a key.";
dictHasKeyQ::usage =
"dictHasKeyQ[dictionary, key] gives True if key in dictionary has not unset.";
dictKeyEmptyQ::usage =
"dictKeyEmptyQ[dictionary, key] gives True if the value of key in dictionary is an empty list.";
dictKeys::usage =
"dictKeys[dictionary] returns all keys in a dictionary.";
dictKeyValuePairs::usage =
"dictKeyValuePairs[dictionary] returns all key value pairs in a dictionary.";
Begin["`Private`"]
makeDictionary[]:=Module[{name},
name=Unique["dict"];
Evaluate[name][k_]:={};
Dictionary[name]
]
destroyDictionary[Dictionary[name_,___]]:=If[ValueQ[name[_]],Remove[name];True,False]
dictName[Dictionary[name_,___]]:=name
dictStore[dict_Dictionary,key_,value_]:=Module[{d=dictName[dict]},d[key]=Prepend[d[key],value]]
dictReplace[dict_Dictionary,key_,value_]:=Module[{d=dictName[dict]},d[key]=Union[d[key],{value}]]
dictRemove[dict_Dictionary,key_,value_]:=Module[{d=dictName[dict]},d[key]=Complement[d[key],{value}]]
dictLookup[Dictionary[name_,___],key_]:=name[key]
dictHasKeyQ[Dictionary[name_,___],key_]:=ValueQ[name[key]]
dictKeyEmptyQ[Dictionary[name_,___],key_]:=name[key]==={}
dictKeys[dict_Dictionary]:=Most[DownValues[Evaluate@dictName[dict]]]/.HoldPattern[a_:>values_List]:>a[[1,1]]
dictKeyValuePairs[dict_Dictionary]:=Most[DownValues[Evaluate[dictName[dict]]]]/.HoldPattern[a_:>values_List]:>{a[[1,1]],values}
Dictionary[name_][prop_] := With[{d = dictLookup[Dictionary[name], prop]}, If[Length@d == 1, First@d, d]]
End[ ]
EndPackage[ ]
A basic example:
sweden = {"Gothenburg", "Stockholm", "Kalmar", "Halmstad"};
unitedstates = {"Clinton", "Terre Haute", "Springfield",
"St. Louis"};
cities = makeDictionary[];
dictStore[cities, "Sweden", #] & /@ sweden;
dictStore[cities, "United States", #] & /@ unitedstates;
dictKeys[cities]
{"Sweden", "United States"}
dictLookup[cities, "United States"]
{"St. Louis", "Springfield", "Terre Haute", "Clinton"}
I've added a shorthand for dictLookup, so that you can retrieve a property easily by just writing dictionary["prop"]
.