dictionary 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/HISTORY ADDED
@@ -0,0 +1,10 @@
1
+ = HISTORY
2
+
3
+ == 1.0.0 / 2009-07-16
4
+
5
+ This is the initial release of Dictionary.
6
+
7
+ * 1 Major Enhancment
8
+
9
+ * Happy Birthday!
10
+
@@ -0,0 +1,21 @@
1
+ test
2
+ test/test_dictionary.rb
3
+ RELEASE
4
+ README
5
+ HISTORY
6
+ meta
7
+ meta/created
8
+ meta/repository
9
+ meta/homepage
10
+ meta/package
11
+ meta/title
12
+ meta/released
13
+ meta/version
14
+ meta/license
15
+ meta/authors
16
+ meta/project
17
+ meta/description
18
+ meta/contact
19
+ lib
20
+ lib/dictionary.rb
21
+ COPYING
data/README ADDED
@@ -0,0 +1,62 @@
1
+ = Dictionary
2
+
3
+ * http://death.rubyforge.org
4
+ * http://death.rubyforge.org/dictionary
5
+
6
+
7
+ == DESCRIPTION
8
+
9
+ The Dictionary class is a type of ordered Hash,
10
+ which keeps it's contents in a customizable order.
11
+
12
+
13
+ == FEATURES/ISSUES
14
+
15
+ * Order is customizable.
16
+ * Compatable with Hash API.
17
+
18
+
19
+ == RELEASE NOTES
20
+
21
+ Please see RELEASE file.
22
+
23
+
24
+ == SYNOPSIS
25
+
26
+ require 'dictionary'
27
+
28
+ dict = Dictionary.new
29
+ dict['z'] = 1
30
+ dict['y'] = 2
31
+ dict['x'] = 3
32
+
33
+ dict.order_by{ |k,v| k }
34
+
35
+ dict.keys #=> ['x', 'y', 'z']
36
+ dict.values #=> [3, 2, 1]
37
+
38
+
39
+ == HOW TO INSTALL
40
+
41
+ To install with RubyGems simply open a console and type:
42
+
43
+ gem install dictionary
44
+
45
+ Local installation requires Setup.rb (gem install setup),
46
+ then download the tarball package and type:
47
+
48
+ tar -xvzf dictionary-1.0.0.tgz
49
+ cd dictionary-1.0.0.tgz
50
+ sudo setup.rb all
51
+
52
+ Windows users use 'ruby setup.rb all'.
53
+
54
+
55
+ == LICENSE
56
+
57
+ Copyright (c) 2005 Jan Molic
58
+
59
+ This program is ditributed unser the terms of the LGPL license.
60
+
61
+ See LICENSE file for details.
62
+
data/RELEASE ADDED
@@ -0,0 +1,10 @@
1
+ = RELEASE NOTES
2
+
3
+ This is the initial release of Dictionary.
4
+
5
+ ### 1.0.0 / 2009-07-16
6
+
7
+ * 1 Major Enhancment
8
+
9
+ * Happy Birthday!
10
+
@@ -0,0 +1,422 @@
1
+ # = Dictionary
2
+ #
3
+ # * Copyright (c) 2009 Thomas Sawyer
4
+ # * Copyright (c) 2005 Jan Molic
5
+ #
6
+ # == Acknowledgments
7
+ #
8
+ # * Andrew Johnson (merge, to_a, inspect, shift and Hash[])
9
+ # * Jeff Sharpe (reverse and reverse!)
10
+ # * Thomas Leitner (has_key? and key?)
11
+ #
12
+ # Ported from OrderHash 2.0, Copyright (c) 2005 Jan Molic
13
+
14
+
15
+ # The Dictionary class is a Hash that preserves order.
16
+ # So it has some array-like extensions also. By defualt
17
+ # a Dictionary object preserves insertion order, but any
18
+ # order can be specified including alphabetical key order.
19
+ #
20
+ # == Usage
21
+ #
22
+ # Just require this file and use Dictionary instead of Hash.
23
+ #
24
+ # # You can do simply
25
+ # hsh = Dictionary.new
26
+ # hsh['z'] = 1
27
+ # hsh['a'] = 2
28
+ # hsh['c'] = 3
29
+ # p hsh.keys #=> ['z','a','c']
30
+ #
31
+ # # or using Dictionary[] method
32
+ # hsh = Dictionary['z', 1, 'a', 2, 'c', 3]
33
+ # p hsh.keys #=> ['z','a','c']
34
+ #
35
+ # # but this don't preserve order
36
+ # hsh = Dictionary['z'=>1, 'a'=>2, 'c'=>3]
37
+ # p hsh.keys #=> ['a','c','z']
38
+ #
39
+ # # Dictionary has useful extensions: push, pop and unshift
40
+ # p hsh.push('to_end', 15) #=> true, key added
41
+ # p hsh.push('to_end', 30) #=> false, already - nothing happen
42
+ # p hsh.unshift('to_begin', 50) #=> true, key added
43
+ # p hsh.unshift('to_begin', 60) #=> false, already - nothing happen
44
+ # p hsh.keys #=> ["to_begin", "a", "c", "z", "to_end"]
45
+ # p hsh.pop #=> ["to_end", 15], if nothing remains, return nil
46
+ # p hsh.keys #=> ["to_begin", "a", "c", "z"]
47
+ # p hsh.shift #=> ["to_begin", 30], if nothing remains, return nil
48
+ #
49
+ # == Usage Notes
50
+ #
51
+ # * You can use #order_by to set internal sort order.
52
+ # * #order_by has the same interface as #sort_by.
53
+ # * #<< takes a two element [k,v] array and inserts.
54
+ # * Use Dictionary::auto to create Dictionary sub-entries on demand.
55
+ # * And Dictionary::alpha wto create a new Dictionary sorted by key.
56
+ #
57
+ class Dictionary
58
+
59
+ include Enumerable
60
+
61
+ class << self
62
+ #--
63
+ # TODO is this needed? Doesn't the super class do this?
64
+ #++
65
+
66
+ def [](*args)
67
+ hsh = new
68
+ if Hash === args[0]
69
+ hsh.replace(args[0])
70
+ elsif (args.size % 2) != 0
71
+ raise ArgumentError, "odd number of elements for Hash"
72
+ else
73
+ while !args.empty?
74
+ hsh[args.shift] = args.shift
75
+ end
76
+ end
77
+ hsh
78
+ end
79
+
80
+ # Like #new but the block sets the order.
81
+ #
82
+ def new_by(*args, &blk)
83
+ new(*args).order_by(&blk)
84
+ end
85
+
86
+ # Alternate to #new which creates a dictionary sorted by key.
87
+ #
88
+ # d = Dictionary.alpha
89
+ # d["z"] = 1
90
+ # d["y"] = 2
91
+ # d["x"] = 3
92
+ # d #=> {"x"=>3,"y"=>2,"z"=>2}
93
+ #
94
+ # This is equivalent to:
95
+ #
96
+ # Dictionary.new.order_by { |key,value| key }
97
+
98
+ def alpha(*args, &block)
99
+ new(*args, &block).order_by_key
100
+ end
101
+
102
+ # Alternate to #new which auto-creates sub-dictionaries as needed.
103
+ #
104
+ # d = Dictionary.auto
105
+ # d["a"]["b"]["c"] = "abc" #=> { "a"=>{"b"=>{"c"=>"abc"}}}
106
+ #
107
+ def auto(*args)
108
+ #AutoDictionary.new(*args)
109
+ leet = lambda { |hsh, key| hsh[key] = new(&leet) }
110
+ new(*args, &leet)
111
+ end
112
+ end
113
+
114
+ # New Dictiionary.
115
+
116
+ def initialize(*args, &blk)
117
+ @order = []
118
+ @order_by = nil
119
+ if blk
120
+ dict = self # This ensure autmatic key entry effect the
121
+ oblk = lambda{ |hsh, key| blk[dict,key] } # dictionary rather then just the interal hash.
122
+ @hash = Hash.new(*args, &oblk)
123
+ else
124
+ @hash = Hash.new(*args)
125
+ end
126
+ end
127
+
128
+ def order
129
+ reorder if @order_by
130
+ @order
131
+ end
132
+
133
+ # Keep dictionary sorted by a specific sort order.
134
+
135
+ def order_by( &block )
136
+ @order_by = block
137
+ order
138
+ self
139
+ end
140
+
141
+ # Keep dictionary sorted by key.
142
+ #
143
+ # d = Dictionary.new.order_by_key
144
+ # d["z"] = 1
145
+ # d["y"] = 2
146
+ # d["x"] = 3
147
+ # d #=> {"x"=>3,"y"=>2,"z"=>2}
148
+ #
149
+ # This is equivalent to:
150
+ #
151
+ # Dictionary.new.order_by { |key,value| key }
152
+ #
153
+ # The initializer Dictionary#alpha also provides this.
154
+
155
+ def order_by_key
156
+ @order_by = lambda { |k,v| k }
157
+ order
158
+ self
159
+ end
160
+
161
+ # Keep dictionary sorted by value.
162
+ #
163
+ # d = Dictionary.new.order_by_value
164
+ # d["z"] = 1
165
+ # d["y"] = 2
166
+ # d["x"] = 3
167
+ # d #=> {"x"=>3,"y"=>2,"z"=>2}
168
+ #
169
+ # This is equivalent to:
170
+ #
171
+ # Dictionary.new.order_by { |key,value| value }
172
+
173
+ def order_by_value
174
+ @order_by = lambda { |k,v| v }
175
+ order
176
+ self
177
+ end
178
+
179
+ #
180
+ def reorder
181
+ if @order_by
182
+ assoc = @order.collect{ |k| [k,@hash[k]] }.sort_by(&@order_by)
183
+ @order = assoc.collect{ |k,v| k }
184
+ end
185
+ @order
186
+ end
187
+
188
+ #def ==( hsh2 )
189
+ # return false if @order != hsh2.order
190
+ # super hsh2
191
+ #end
192
+
193
+ def ==(hsh2)
194
+ if hsh2.is_a?( Dictionary )
195
+ @order == hsh2.order &&
196
+ @hash == hsh2.instance_variable_get("@hash")
197
+ else
198
+ false
199
+ end
200
+ end
201
+
202
+ def [] k
203
+ @hash[ k ]
204
+ end
205
+
206
+ def fetch(k, *a, &b)
207
+ @hash.fetch(k, *a, &b)
208
+ end
209
+
210
+ # Store operator.
211
+ #
212
+ # h[key] = value
213
+ #
214
+ # Or with additional index.
215
+ #
216
+ # h[key,index] = value
217
+
218
+ def []=(k, i=nil, v=nil)
219
+ if v
220
+ insert(i,k,v)
221
+ else
222
+ store(k,i)
223
+ end
224
+ end
225
+
226
+ def insert( i,k,v )
227
+ @order.insert( i,k )
228
+ @hash.store( k,v )
229
+ end
230
+
231
+ def store( a,b )
232
+ @order.push( a ) unless @hash.has_key?( a )
233
+ @hash.store( a,b )
234
+ end
235
+
236
+ def clear
237
+ @order = []
238
+ @hash.clear
239
+ end
240
+
241
+ def delete( key )
242
+ @order.delete( key )
243
+ @hash.delete( key )
244
+ end
245
+
246
+ def each_key
247
+ order.each { |k| yield( k ) }
248
+ self
249
+ end
250
+
251
+ def each_value
252
+ order.each { |k| yield( @hash[k] ) }
253
+ self
254
+ end
255
+
256
+ def each
257
+ order.each { |k| yield( k,@hash[k] ) }
258
+ self
259
+ end
260
+ alias each_pair each
261
+
262
+ def delete_if
263
+ order.clone.each { |k| delete k if yield(k,@hash[k]) }
264
+ self
265
+ end
266
+
267
+ def values
268
+ ary = []
269
+ order.each { |k| ary.push @hash[k] }
270
+ ary
271
+ end
272
+
273
+ def keys
274
+ order
275
+ end
276
+
277
+ def invert
278
+ hsh2 = self.class.new
279
+ order.each { |k| hsh2[@hash[k]] = k }
280
+ hsh2
281
+ end
282
+
283
+ def reject(&block)
284
+ self.dup.delete_if(&block)
285
+ end
286
+
287
+ def reject!( &block )
288
+ hsh2 = reject(&block)
289
+ self == hsh2 ? nil : hsh2
290
+ end
291
+
292
+ def replace(hsh2)
293
+ case hsh2
294
+ when Hash
295
+ @order = hsh2.keys
296
+ @hash = hsh2
297
+ else
298
+ @order = hsh2.order
299
+ @hash = hsh2.hash
300
+ end
301
+ reorder
302
+ end
303
+
304
+ def shift
305
+ key = order.first
306
+ key ? [key,delete(key)] : super
307
+ end
308
+
309
+ def unshift( k,v )
310
+ unless @hash.include?( k )
311
+ @order.unshift( k )
312
+ @hash.store( k,v )
313
+ true
314
+ else
315
+ false
316
+ end
317
+ end
318
+
319
+ def <<(kv)
320
+ push(*kv)
321
+ end
322
+
323
+ def push( k,v )
324
+ unless @hash.include?( k )
325
+ @order.push( k )
326
+ @hash.store( k,v )
327
+ true
328
+ else
329
+ false
330
+ end
331
+ end
332
+
333
+ def pop
334
+ key = order.last
335
+ key ? [key,delete(key)] : nil
336
+ end
337
+
338
+ def inspect
339
+ ary = []
340
+ each {|k,v| ary << k.inspect + "=>" + v.inspect}
341
+ '{' + ary.join(", ") + '}'
342
+ end
343
+
344
+ def dup
345
+ a = []
346
+ each{ |k,v| a << k; a << v }
347
+ self.class[*a]
348
+ end
349
+
350
+ def update( hsh2 )
351
+ hsh2.each { |k,v| self[k] = v }
352
+ reorder
353
+ self
354
+ end
355
+ alias :merge! update
356
+
357
+ def merge( hsh2 )
358
+ self.dup.update(hsh2)
359
+ end
360
+
361
+ def select
362
+ ary = []
363
+ each { |k,v| ary << [k,v] if yield k,v }
364
+ ary
365
+ end
366
+
367
+ def reverse!
368
+ @order.reverse!
369
+ self
370
+ end
371
+
372
+ def reverse
373
+ dup.reverse!
374
+ end
375
+
376
+ #
377
+ def first(x=nil)
378
+ return @hash[order.first] unless x
379
+ order.first(x).collect { |k| @hash[k] }
380
+ end
381
+
382
+ #
383
+ def last(x=nil)
384
+ return @hash[order.last] unless x
385
+ order.last(x).collect { |k| @hash[k] }
386
+ end
387
+
388
+ def length
389
+ @order.length
390
+ end
391
+ alias :size :length
392
+
393
+ def empty?
394
+ @hash.empty?
395
+ end
396
+
397
+ def has_key?(key)
398
+ @hash.has_key?(key)
399
+ end
400
+
401
+ def key?(key)
402
+ @hash.key?(key)
403
+ end
404
+
405
+ def to_a
406
+ ary = []
407
+ each { |k,v| ary << [k,v] }
408
+ ary
409
+ end
410
+
411
+ def to_s
412
+ self.to_a.to_s
413
+ end
414
+
415
+ def to_hash
416
+ @hash.dup
417
+ end
418
+
419
+ def to_h
420
+ @hash.dup
421
+ end
422
+ end