Project

General

Profile

root / branches / compiler / cSharp / ooasCompiler / src / libs / c5 / UserGuideExamples / MultiDictionary-njk.cs @ 3

1
/*
2
 Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
3

    
4
 Permission is hereby granted, free of charge, to any person obtaining a copy
5
 of this software and associated documentation files (the "Software"), to deal
6
 in the Software without restriction, including without limitation the rights
7
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
 copies of the Software, and to permit persons to whom the Software is
9
 furnished to do so, subject to the following conditions:
10
 
11
 The above copyright notice and this permission notice shall be included in
12
 all copies or substantial portions of the Software.
13
 
14
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
 SOFTWARE.
21
*/
22

    
23
// C5 example: 2006-01-29
24

    
25
// Compile with 
26
//   csc /r:C5.dll MultiDictionary.cs 
27

    
28
using System;
29
using C5;
30
using SCG = System.Collections.Generic;
31

    
32
namespace MultiDictionaries
33
{
34
  using Inner = HashSet<String>;
35

    
36
  using MultiDictionary3;
37

    
38
  public class MyTest
39
  {
40
    public static void Main()
41
    {
42
      MultiHashDictionary<int, String, Inner> mdict = new MultiHashDictionary<int, String, Inner>();
43
      mdict.Add(2, "to");
44
      mdict.Add(2, "deux");
45
      mdict.Add(2, "two");
46
      mdict.Add(20, "tyve");
47
      mdict.Add(20, "tyve");
48
      mdict.Add(20, "twenty");
49
      Console.WriteLine(mdict);
50
      Console.WriteLine("mdict.Count is {0}", mdict.Count);
51
      Console.WriteLine("mdict.Count (keys) is {0}",
52
                        ((IDictionary<int, Inner>)mdict).Count);
53
      Console.WriteLine("mdict[2].Count is {0}", mdict[2].Count);
54
      mdict.Remove(20, "tyve");
55
      mdict.Remove(20, "twenty");
56
      Console.WriteLine(mdict);
57
      Console.WriteLine("mdict.Count is {0}", mdict.Count);
58
      Inner zwei = new Inner();
59
      zwei.Add("zwei");
60
      mdict[2] = zwei;
61
      mdict[-2] = zwei;
62
      Console.WriteLine(mdict);
63
      Console.WriteLine("mdict.Count is {0}", mdict.Count);
64
      zwei.Add("kaksi");
65
      Console.WriteLine(mdict);
66
      Console.WriteLine("mdict.Count is {0}", mdict.Count);
67
      Inner empty = new Inner();
68
      mdict[0] = empty;
69
      Console.WriteLine(mdict);
70
      Console.WriteLine("mdict.Count is {0}", mdict.Count);
71
      Console.WriteLine("mdict contains key 0: {0}", mdict.Contains(0));
72
      mdict.Remove(-2);
73
      Console.WriteLine(mdict);
74
      Console.WriteLine("mdict.Count is {0}", mdict.Count);
75
      zwei.Remove("kaksi");
76
      Console.WriteLine(mdict);
77
      Console.WriteLine("mdict.Count is {0}", mdict.Count);
78
      zwei.Clear();
79
      Console.WriteLine(mdict);
80
      Console.WriteLine("mdict.Count is {0}", mdict.Count);
81
    }
82
  }
83
}
84

    
85
namespace MultiDictionary1
86
{
87
  // Here we implement a multivalued dictionary as a hash dictionary
88
  // from keys to value collections.  The value collections may have set
89
  // or bag semantics.
90

    
91
  // The value collections are externally modifiable (as in Peter
92
  // Golde's PowerCollections library), and therefore:
93
  //
94
  //  * A value collection associated with a key may be null or
95
  //  non-empty.  Hence for correct semantics, the Contains(k) method
96
  //  must check that the value collection associated with a key is
97
  //  non-null and non-empty.
98
  //  
99
  //  * A value collection may be shared between two or more keys.
100
  //
101

    
102
  // A C5 hash dictionary each of whose keys map to a collection of values.
103

    
104
  public class MultiHashDictionary<K, V> : HashDictionary<K, ICollection<V>>
105
  {
106

    
107
    // Return total count of values associated with keys.  This basic
108
    // implementation simply sums over all value collections, and so
109
    // is a linear-time operation in the total number of values.  
110

    
111
    public new virtual int Count
112
    {
113
      get
114
      {
115
        int count = 0;
116
        foreach (KeyValuePair<K, ICollection<V>> entry in this)
117
          if (entry.Value != null)
118
            count += entry.Value.Count;
119
        return count;
120
      }
121
    }
122

    
123
    public override Speed CountSpeed
124
    {
125
      get { return Speed.Linear; }
126
    }
127

    
128
    // Add a (key,value) pair
129

    
130
    public virtual void Add(K k, V v)
131
    {
132
      ICollection<V> values;
133
      if (!base.Find(k, out values) || values == null)
134
      {
135
        values = new HashSet<V>();
136
        Add(k, values);
137
      }
138
      values.Add(v);
139
    }
140

    
141
    // Remove a single (key,value) pair, if present; return true if
142
    // anything was removed, else false
143

    
144
    public virtual bool Remove(K k, V v)
145
    {
146
      ICollection<V> values;
147
      if (base.Find(k, out values) && values != null)
148
      {
149
        if (values.Remove(v))
150
        {
151
          if (values.IsEmpty)
152
            base.Remove(k);
153
          return true;
154
        }
155
      }
156
      return false;
157
    }
158

    
159
    // Determine whether key k is associated with a value
160

    
161
    public override bool Contains(K k)
162
    {
163
      ICollection<V> values;
164
      return Find(k, out values) && values != null && !values.IsEmpty;
165
    }
166

    
167
    // Determine whether each key in ks is associated with a value
168

    
169
    public override bool ContainsAll<U>(SCG.IEnumerable<U> ks)
170
    {
171
      foreach (K k in ks)
172
        if (!Contains(k))
173
          return false;
174
      return true;
175
    }
176

    
177
    // Get or set the value collection associated with key k
178

    
179
    public override ICollection<V> this[K k]
180
    {
181
      get
182
      {
183
        ICollection<V> values;
184
        return base.Find(k, out values) && values != null ? values : new HashSet<V>();
185
      }
186
      set
187
      {
188
        base[k] = value;
189
      }
190
    }
191

    
192
    // Inherited from base class HashDictionary<K,ICollection<V>>:
193

    
194
    // Add(K k, ICollection<V> values) 
195
    // AddAll(IEnumerable<KeyValuePair<K,ICollection<V>>> kvs) 
196
    // Clear
197
    // Clone
198
    // Find(K k, out ICollection<V> values)
199
    // Find(ref K k, out ICollection<V> values)
200
    // FindOrAdd(K k, ref ICollection<V> values) 
201
    // Remove(K k) 
202
    // Remove(K k, out ICollection<V> values) 
203
    // Update(K k, ICollection<V> values)
204
    // Update(K k, ICollection<V> values, out ICollection<V> oldValues)
205
    // UpdateOrAdd(K k, ICollection<V> values)
206
    // UpdateOrAdd(K k, ICollection<V> values, out ICollection<V> oldValues)
207
  }
208
}
209

    
210

    
211
namespace MultiDictionary2
212
{
213
  // Here we implement a multivalued dictionary as a hash dictionary
214
  // from keys to value collections.  The value collections may have
215
  // set or bag semantics.  This version uses event listeners to make
216
  // the Count operation constant time.
217

    
218
  //  * To avoid recomputing the total number of values for the Count
219
  //  property, one may cache it and then use event listeners on the
220
  //  value collections to keep the cached count updated.  In turn, this
221
  //  requires such event listeners on the dictionary also.
222

    
223
  // A C5 hash dictionary each of whose keys map to a collection of values.
224

    
225
  public class MultiHashDictionary<K, V> : HashDictionary<K, ICollection<V>>
226
  {
227
    private int count = 0;      // Cached value count, updated by events only
228

    
229
    private void IncrementCount(Object sender, ItemCountEventArgs<V> args)
230
    {
231
      count += args.Count;
232
    }
233

    
234
    private void DecrementCount(Object sender, ItemCountEventArgs<V> args)
235
    {
236
      count -= args.Count;
237
    }
238

    
239
    private void ClearedCount(Object sender, ClearedEventArgs args)
240
    {
241
      count -= args.Count;
242
    }
243

    
244
    public MultiHashDictionary()
245
    {
246
      ItemsAdded +=
247
        delegate(Object sender, ItemCountEventArgs<KeyValuePair<K, ICollection<V>>> args)
248
        {
249
          ICollection<V> values = args.Item.Value;
250
          if (values != null)
251
          {
252
            count += values.Count;
253
            values.ItemsAdded += IncrementCount;
254
            values.ItemsRemoved += DecrementCount;
255
            values.CollectionCleared += ClearedCount;
256
          }
257
        };
258
      ItemsRemoved +=
259
        delegate(Object sender, ItemCountEventArgs<KeyValuePair<K, ICollection<V>>> args)
260
        {
261
          ICollection<V> values = args.Item.Value;
262
          if (values != null)
263
          {
264
            count -= values.Count;
265
            values.ItemsAdded -= IncrementCount;
266
            values.ItemsRemoved -= DecrementCount;
267
            values.CollectionCleared -= ClearedCount;
268
          }
269
        };
270
    }
271

    
272
    // Return total count of values associated with keys.  
273

    
274
    public new virtual int Count
275
    {
276
      get
277
      {
278
        return count;
279
      }
280
    }
281

    
282
    public override Speed CountSpeed
283
    {
284
      get { return Speed.Constant; }
285
    }
286

    
287
    // Add a (key,value) pair
288

    
289
    public virtual void Add(K k, V v)
290
    {
291
      ICollection<V> values;
292
      if (!base.Find(k, out values) || values == null)
293
      {
294
        values = new HashSet<V>();
295
        Add(k, values);
296
      }
297
      values.Add(v);
298
    }
299

    
300
    // Remove a single (key,value) pair, if present; return true if
301
    // anything was removed, else false
302

    
303
    public virtual bool Remove(K k, V v)
304
    {
305
      ICollection<V> values;
306
      if (base.Find(k, out values) && values != null)
307
      {
308
        if (values.Remove(v))
309
        {
310
          if (values.IsEmpty)
311
            base.Remove(k);
312
          return true;
313
        }
314
      }
315
      return false;
316
    }
317

    
318
    // Determine whether key k is associated with a value
319

    
320
    public override bool Contains(K k)
321
    {
322
      ICollection<V> values;
323
      return Find(k, out values) && values != null && !values.IsEmpty;
324
    }
325

    
326
    // Determine whether each key in ks is associated with a value
327

    
328
    public override bool ContainsAll<U>(SCG.IEnumerable<U> ks)
329
    {
330
      foreach (K k in ks)
331
        if (!Contains(k))
332
          return false;
333
      return true;
334
    }
335

    
336
    // Get or set the value collection associated with key k
337

    
338
    public override ICollection<V> this[K k]
339
    {
340
      get
341
      {
342
        ICollection<V> values;
343
        return base.Find(k, out values) && values != null ? values : new HashSet<V>();
344
      }
345
      set
346
      {
347
        base[k] = value;
348
      }
349
    }
350
  }
351
}
352

    
353

    
354
namespace MultiDictionary3
355
{
356
  // Here we implement a multivalued dictionary as a hash dictionary
357
  // from keys to value collections.  The value collections may have
358
  // set or bag semantics.  This version uses event listeners to make
359
  // the Count operation constant time.
360

    
361
  //  * To avoid recomputing the total number of values for the Count
362
  //  property, one may cache it and then use event listeners on the
363
  //  value collections to keep the cached count updated.  In turn, this
364
  //  requires such event listeners on the dictionary also.
365

    
366
  // A C5 hash dictionary each of whose keys map to a collection of values.
367

    
368
  public class MultiHashDictionary<K, V, W> : HashDictionary<K, W> where W : ICollection<V>, new()
369
  {
370
    private int count = 0;      // Cached value count, updated by events only
371

    
372
    private void IncrementCount(Object sender, ItemCountEventArgs<V> args)
373
    {
374
      count += args.Count;
375
    }
376

    
377
    private void DecrementCount(Object sender, ItemCountEventArgs<V> args)
378
    {
379
      count -= args.Count;
380
    }
381

    
382
    private void ClearedCount(Object sender, ClearedEventArgs args)
383
    {
384
      count -= args.Count;
385
    }
386

    
387
    public MultiHashDictionary()
388
    {
389
      ItemsAdded +=
390
        delegate(Object sender, ItemCountEventArgs<KeyValuePair<K, W>> args)
391
        {
392
          ICollection<V> values = args.Item.Value;
393
          if (values != null)
394
          {
395
            count += values.Count;
396
            values.ItemsAdded += IncrementCount;
397
            values.ItemsRemoved += DecrementCount;
398
            values.CollectionCleared += ClearedCount;
399
          }
400
        };
401
      ItemsRemoved +=
402
        delegate(Object sender, ItemCountEventArgs<KeyValuePair<K, W>> args)
403
        {
404
          ICollection<V> values = args.Item.Value;
405
          if (values != null)
406
          {
407
            count -= values.Count;
408
            values.ItemsAdded -= IncrementCount;
409
            values.ItemsRemoved -= DecrementCount;
410
            values.CollectionCleared -= ClearedCount;
411
          }
412
        };
413
    }
414

    
415
    // Return total count of values associated with keys.  
416

    
417
    public new virtual int Count
418
    {
419
      get
420
      {
421
        return count;
422
      }
423
    }
424

    
425
    public override Speed CountSpeed
426
    {
427
      get { return Speed.Constant; }
428
    }
429

    
430
    // Add a (key,value) pair
431

    
432
    public virtual void Add(K k, V v)
433
    {
434
      W values;
435
      if (!base.Find(k, out values) || values == null)
436
      {
437
        values = new W();
438
        Add(k, values);
439
      }
440
      values.Add(v);
441
    }
442

    
443
    // Remove a single (key,value) pair, if present; return true if
444
    // anything was removed, else false
445

    
446
    public virtual bool Remove(K k, V v)
447
    {
448
      W values;
449
      if (base.Find(k, out values) && values != null)
450
      {
451
        if (values.Remove(v))
452
        {
453
          if (values.IsEmpty)
454
            base.Remove(k);
455
          return true;
456
        }
457
      }
458
      return false;
459
    }
460

    
461
    // Determine whether key k is associated with a value
462

    
463
    public override bool Contains(K k)
464
    {
465
      W values;
466
      return Find(k, out values) && values != null && !values.IsEmpty;
467
    }
468

    
469
    // Determine whether each key in ks is associated with a value
470

    
471
    public override bool ContainsAll<U>(SCG.IEnumerable<U> ks)
472
    {
473
      foreach (K k in ks)
474
        if (!Contains(k))
475
          return false;
476
      return true;
477
    }
478

    
479
    // Get or set the value collection associated with key k
480

    
481
    public override W this[K k]
482
    {
483
      get
484
      {
485
        W values;
486
        return base.Find(k, out values) && values != null ? values : new W();
487
      }
488
      set
489
      {
490
        base[k] = value;
491
      }
492
    }
493
  }
494
}