root/trunk/docsrc/hash-map.dd

Revision 2127, 7.1 kB (checked in by walter, 2 years ago)

tweak aa's

Line 
1 Ddoc
2
3 $(SPEC_S Associative Arrays,
4
5     $(P Associative arrays have an index that is not necessarily an integer,
6     and can be sparsely populated. The index for an associative array
7     is called the $(I key), and its type is called the $(I KeyType).
8     )
9
10     $(P Associative arrays are declared by placing the $(I KeyType)
11     within the [] of an array declaration:
12     )
13
14 ---------
15 int[char[]] b;      // associative array b of ints that are
16             // indexed by an array of characters.
17             // The $(I KeyType) is char[]
18 b["hello"] = 3;     // set value associated with key "hello" to 3
19 func(b["hello"]);   // pass 3 as parameter to func()
20 ---------
21
22     $(P Particular keys in an associative array can be removed with the
23     remove function:
24     )
25
26 ---------
27 b.$(B remove)("hello");
28 ---------
29
30     $(P The $(I InExpression) yields a pointer to the value
31     if the key is in the associative array, or $(B null) if not:
32     )
33
34 ---------
35 int* p;
36 p = ("hello" $(B in) b);
37 if (p != $(B null))
38     ...
39 ---------
40
41     $(P $(I KeyType)s cannot be functions or voids.
42     )
43
44     $(P The element types of an associative array cannot be functions or voids.)
45
46 <h3>Using Classes as the KeyType</h3>
47
48     $(P Classes can be used as the $(I KeyType). For this to work,
49     the class definition must override the following member functions
50     of class $(TT Object):)
51
52     $(UL
53     $(LI $(TT hash_t toHash()))
54 $(V1    $(LI $(TT int opEquals(Object))))
55 $(V2    $(LI $(TT bool opEquals(Object))))
56     $(LI $(TT int opCmp(Object)))
57     )
58
59     $(P $(TT hash_t) is an alias to an integral type.)
60
61     $(P Note that the parameter to $(TT opCmp) and $(TT opEquals) is
62     of type
63     $(TT Object), not the type of the class in which it is defined.)
64
65     $(P For example:)
66
67 ---
68 class Foo
69 {
70     int a, b;
71
72     hash_t $(B toHash)() { return a + b; }
73
74 $(V1      int $(B opEquals)(Object o))$(V2      bool $(B opEquals)(Object o))
75     {   Foo f = cast(Foo) o;
76     return f && a == foo.a && b == foo.b;
77     }
78
79     int $(B opCmp)(Object o)
80     {   Foo f = cast(Foo) o;
81     if (!f)
82         return -1;
83     if (a == foo.a)
84         return b - foo.b;
85     return a - foo.a;
86     }
87 }
88 ---
89
90     $(P The implementation may use either $(TT opEquals) or $(TT opCmp) or
91     both. Care should be taken so that the results of
92     $(TT opEquals) and $(TT opCmp) are consistent with each other when
93     the class objects are the same or not.)
94
95 <h3>Using Structs or Unions as the KeyType</h3>
96
97     $(P If the $(I KeyType) is a struct or union type,
98     a default mechanism is used
99     to compute the hash and comparisons of it based on the binary
100     data within the struct value. A custom mechanism can be used
101     by providing the following functions as struct members:
102     )
103
104 ---------
105 $(V2 const) hash_t $(B toHash)();
106 $(V1 int $(B opEquals)($(I KeyType)* s);)$(V2 const bool $(B opEquals)(ref const $(I KeyType) s);)
107 $(V1 int $(B opCmp)($(I KeyType)* s);)$(V2 const int $(B opCmp)(ref const $(I KeyType) s);)
108 ---------
109
110     $(P For example:)
111
112 ---------
113 import std.string;
114
115 struct MyString
116 {
117     string str;
118
119 $(V1      hash_t $(B toHash)()
120     {   hash_t hash;
121     foreach (char c; s)
122         hash = (hash * 9) + c;
123     return hash;
124     }
125
126     bool $(B opEquals)(MyString* s)
127     {
128     return std.string.cmp(this.str, s.str) == 0;
129     }
130
131     int $(B opCmp)(MyString* s)
132     {
133     return std.string.cmp(this.str, s.str);
134     })
135 $(V2      const hash_t $(B toHash)()
136     {   hash_t hash;
137     foreach (char c; s)
138         hash = (hash * 9) + c;
139     return hash;
140     }
141
142     const bool $(B opEquals)(ref const MyString s)
143     {
144     return std.string.cmp(this.str, s.str) == 0;
145     }
146
147     const int $(B opCmp)(ref const MyString s)
148     {
149     return std.string.cmp(this.str, s.str);
150     })
151 }
152 ---------
153
154
155     $(P The implementation may use either $(TT opEquals) or $(TT opCmp) or
156     both. Care should be taken so that the results of
157     $(TT opEquals) and $(TT opCmp) are consistent with each other when
158     the struct/union objects are the same or not.)
159
160 <h3>Properties</h3>
161
162 Properties for associative arrays are:
163
164     $(TABLE2 Associative Array Properties,
165     $(TR $(TH Property) $(TH Description))
166
167     $(TR
168     $(TD $(B .sizeof))
169     $(TD Returns the size of the reference to the associative
170     array; it is typically 8.
171     )
172     )
173
174     $(TR
175     $(TD $(B .length))
176     $(TD Returns number of values in the associative array.
177     Unlike for dynamic arrays, it is read-only.
178     )
179     )
180
181     $(TR
182     $(TD $(B .keys))
183     $(TD Returns dynamic array, the elements of which are the keys in
184     the associative array.
185     )
186     )
187
188     $(TR
189     $(TD $(B .values))
190     $(TD Returns dynamic array, the elements of which are the values in
191     the associative array.
192     )
193     )
194
195     $(TR
196     $(TD $(B .rehash))
197     $(TD Reorganizes the associative array in place so that lookups
198     are more efficient. rehash is effective when, for example,
199     the program is done loading up a symbol table and now needs
200     fast lookups in it.
201     Returns a reference to the reorganized array.
202     )
203     )
204
205 $(V2
206     $(TR
207     $(TD $(B .byKey()))
208     $(TD Returns a delegate suitable for use as an $(I Aggregate) to
209     a $(LINK2 statement.html#ForeachStatement, $(I ForeachStatement))
210     which will iterate over the keys
211     of the associative array.
212     )
213     )
214
215     $(TR
216     $(TD $(B .byValue()))
217     $(TD Returns a delegate suitable for use as an $(I Aggregate) to
218     a $(LINK2 statement.html#ForeachStatement, $(I ForeachStatement))
219     which will iterate over the values
220     of the associative array.
221     )
222     )
223
224     $(TR
225     $(TD $(B .get(Key key, lazy Value defaultValue)))
226     $(TD Looks up $(I key); if it exists returns corresponding $(I value)
227     else evaluates and returns $(I defaultValue).
228     )
229     )
230 )
231     )
232
233 <hr>
234 <h3>Associative Array Example: word count</h3>
235
236 ---------
237 import std.file;         // D file I/O
238 import std.stdio;
239
240 int main (string[] args)
241 {
242     int word_total;
243     int line_total;
244     int char_total;
245     int[char[]] dictionary;
246
247     writefln("   lines   words   bytes file");
248     for (int i = 1; i < args.length; ++i)      // program arguments
249     {
250     char[] input;            // input buffer
251     int w_cnt, l_cnt, c_cnt; // word, line, char counts
252     int inword;
253     int wstart;
254
255     // read file into input[]
256     input = cast(char[])std.file.read(args[i]);
257
258     foreach (j, char c; input)
259     {
260         if (c == '\n')
261             ++l_cnt;
262         if (c >= '0' && c <= '9')
263         {
264         }
265         else if (c >= 'a' && c <= 'z' ||
266             c >= 'A' && c <= 'Z')
267         {
268         if (!inword)
269         {
270             wstart = j;
271             inword = 1;
272             ++w_cnt;
273         }
274         }
275         else if (inword)
276         {
277         char[] word = input[wstart .. j];
278         dictionary[word]++;        // increment count for word
279         inword = 0;
280         }
281         ++c_cnt;
282     }
283     if (inword)
284     {
285         char[] word = input[wstart .. input.length];
286         dictionary[word]++;
287     }
288     writefln("%8d%8d%8d %s", l_cnt, w_cnt, c_cnt, args[i]);
289     line_total += l_cnt;
290     word_total += w_cnt;
291     char_total += c_cnt;
292     }
293
294     if (args.length > 2)
295     {
296     writef("-------------------------------------\n%8d%8d%8d total",
297         line_total, word_total, char_total);
298     }
299
300     writefln("-------------------------------------");
301     foreach (word; dictionary.keys.sort)
302     {
303     writefln("%3d %s", dictionary[word], word);
304     }
305     return 0;
306 }
307 ---------
308
309 )
310
311 Macros:
312     TITLE=Associative Arrays
313     WIKI=AssociativeArrays
314     DOLLAR=$
315     FOO=
Note: See TracBrowser for help on using the browser.