dictionary 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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