| Class | Dictionary |
| In: |
lib/more/facets/dictionary.rb
|
| Parent: | Object |
The Dictionary class is a Hash that preserves order. So it has some array-like extensions also. By defualt a Dictionary object preserves insertion order, but any order can be specified including alphabetical key order.
Just require this file and use Dictionary instead of Hash.
# You can do simply
hsh = Dictionary.new
hsh['z'] = 1
hsh['a'] = 2
hsh['c'] = 3
p hsh.keys #=> ['z','a','c']
# or using Dictionary[] method
hsh = Dictionary['z', 1, 'a', 2, 'c', 3]
p hsh.keys #=> ['z','a','c']
# but this don't preserve order
hsh = Dictionary['z'=>1, 'a'=>2, 'c'=>3]
p hsh.keys #=> ['a','c','z']
# Dictionary has useful extensions: push, pop and unshift
p hsh.push('to_end', 15) #=> true, key added
p hsh.push('to_end', 30) #=> false, already - nothing happen
p hsh.unshift('to_begin', 50) #=> true, key added
p hsh.unshift('to_begin', 60) #=> false, already - nothing happen
p hsh.keys #=> ["to_begin", "a", "c", "z", "to_end"]
p hsh.pop #=> ["to_end", 15], if nothing remains, return nil
p hsh.keys #=> ["to_begin", "a", "c", "z"]
p hsh.shift #=> ["to_begin", 30], if nothing remains, return nil
# File lib/more/facets/dictionary.rb, line 128
128: def [](*args)
129: hsh = new
130: if Hash === args[0]
131: hsh.replace(args[0])
132: elsif (args.size % 2) != 0
133: raise ArgumentError, "odd number of elements for Hash"
134: else
135: while !args.empty?
136: hsh[args.shift] = args.shift
137: end
138: end
139: hsh
140: end
Alternate to new which creates a dictionary sorted by key.
d = Dictionary.alpha
d["z"] = 1
d["y"] = 2
d["x"] = 3
d #=> {"x"=>3,"y"=>2,"z"=>2}
This is equivalent to:
Dictionary.new.order_by { |key,value| key }
# File lib/more/facets/dictionary.rb, line 160
160: def alpha(*args, &block)
161: new(*args, &block).order_by_key
162: end
Alternate to new which auto-creates sub-dictionaries as needed.
d = Dictionary.auto
d["a"]["b"]["c"] = "abc" #=> { "a"=>{"b"=>{"c"=>"abc"}}}
# File lib/more/facets/dictionary.rb, line 169
169: def auto(*args)
170: #AutoDictionary.new(*args)
171: leet = lambda { |hsh, key| hsh[key] = new(&leet) }
172: new(*args, &leet)
173: end
New Dictiionary.
# File lib/more/facets/dictionary.rb, line 178
178: def initialize(*args, &blk)
179: @order = []
180: @order_by = nil
181: if blk
182: dict = self # This ensure autmatic key entry effect the
183: oblk = lambda{ |hsh, key| blk[dict,key] } # dictionary rather then just the interal hash.
184: @hash = Hash.new(*args, &oblk)
185: else
186: @hash = Hash.new(*args)
187: end
188: end
def ==( hsh2 )
return false if @order != hsh2.order super hsh2
end
# File lib/more/facets/dictionary.rb, line 255
255: def ==(hsh2)
256: if hsh2.is_a?( Dictionary )
257: @order == hsh2.order &&
258: @hash == hsh2.instance_variable_get("@hash")
259: else
260: false
261: end
262: end
Store operator.
h[key] = value
Or with additional index.
h[key,index] = value
# File lib/more/facets/dictionary.rb, line 280
280: def []=(k, i=nil, v=nil)
281: if v
282: insert(i,k,v)
283: else
284: store(k,i)
285: end
286: end
# File lib/more/facets/dictionary.rb, line 298
298: def clear
299: @order = []
300: @hash.clear
301: end
# File lib/more/facets/dictionary.rb, line 303
303: def delete( key )
304: @order.delete( key )
305: @hash.delete( key )
306: end
# File lib/more/facets/dictionary.rb, line 324
324: def delete_if
325: order.clone.each { |k| delete k if yield(k,@hash[k]) }
326: self
327: end
# File lib/more/facets/dictionary.rb, line 406
406: def dup
407: a = []
408: each{ |k,v| a << k; a << v }
409: self.class[*a]
410: end
# File lib/more/facets/dictionary.rb, line 318
318: def each
319: order.each { |k| yield( k,@hash[k] ) }
320: self
321: end
# File lib/more/facets/dictionary.rb, line 308
308: def each_key
309: order.each { |k| yield( k ) }
310: self
311: end
# File lib/more/facets/dictionary.rb, line 313
313: def each_value
314: order.each { |k| yield( @hash[k] ) }
315: self
316: end
# File lib/more/facets/dictionary.rb, line 268
268: def fetch(k, *a, &b)
269: @hash.fetch(k, *a, &b)
270: end
# File lib/more/facets/dictionary.rb, line 439
439: def first(x=nil)
440: return @hash[order.first] unless x
441: order.first(x).collect { |k| @hash[k] }
442: end
# File lib/more/facets/dictionary.rb, line 459
459: def has_key?(key)
460: @hash.has_key?(key)
461: end
# File lib/more/facets/dictionary.rb, line 288
288: def insert( i,k,v )
289: @order.insert( i,k )
290: @hash.store( k,v )
291: end
# File lib/more/facets/dictionary.rb, line 400
400: def inspect
401: ary = []
402: each {|k,v| ary << k.inspect + "=>" + v.inspect}
403: '{' + ary.join(", ") + '}'
404: end
# File lib/more/facets/dictionary.rb, line 339
339: def invert
340: hsh2 = self.class.new
341: order.each { |k| hsh2[@hash[k]] = k }
342: hsh2
343: end
# File lib/more/facets/dictionary.rb, line 445
445: def last(x=nil)
446: return @hash[order.last] unless x
447: order.last(x).collect { |k| @hash[k] }
448: end
# File lib/more/facets/dictionary.rb, line 419
419: def merge( hsh2 )
420: self.dup.update(hsh2)
421: end
# File lib/more/facets/dictionary.rb, line 190
190: def order
191: reorder if @order_by
192: @order
193: end
Keep dictionary sorted by key.
d = Dictionary.new.order_by_key
d["z"] = 1
d["y"] = 2
d["x"] = 3
d #=> {"x"=>3,"y"=>2,"z"=>2}
This is equivalent to:
Dictionary.new.order_by { |key,value| key }
The initializer Dictionary#alpha also provides this.
# File lib/more/facets/dictionary.rb, line 217
217: def order_by_key
218: @order_by = lambda { |k,v| k }
219: order
220: self
221: end
Keep dictionary sorted by value.
d = Dictionary.new.order_by_value
d["z"] = 1
d["y"] = 2
d["x"] = 3
d #=> {"x"=>3,"y"=>2,"z"=>2}
This is equivalent to:
Dictionary.new.order_by { |key,value| value }
# File lib/more/facets/dictionary.rb, line 235
235: def order_by_value
236: @order_by = lambda { |k,v| v }
237: order
238: self
239: end
# File lib/more/facets/dictionary.rb, line 395
395: def pop
396: key = order.last
397: key ? [key,delete(key)] : nil
398: end
# File lib/more/facets/dictionary.rb, line 385
385: def push( k,v )
386: unless @hash.include?( k )
387: @order.push( k )
388: @hash.store( k,v )
389: true
390: else
391: false
392: end
393: end
# File lib/more/facets/dictionary.rb, line 345
345: def reject(&block)
346: self.dup.delete_if(&block)
347: end
# File lib/more/facets/dictionary.rb, line 349
349: def reject!( &block )
350: hsh2 = reject(&block)
351: self == hsh2 ? nil : hsh2
352: end
# File lib/more/facets/dictionary.rb, line 242
242: def reorder
243: if @order_by
244: assoc = @order.collect{ |k| [k,@hash[k]] }.sort_by(&@order_by)
245: @order = assoc.collect{ |k,v| k }
246: end
247: @order
248: end
# File lib/more/facets/dictionary.rb, line 354
354: def replace(hsh2)
355: case hsh2
356: when Hash
357: @order = hsh2.keys
358: @hash = hsh2
359: else
360: @order = hsh2.order
361: @hash = hsh2.hash
362: end
363: reorder
364: end
# File lib/more/facets/dictionary.rb, line 429
429: def reverse!
430: @order.reverse!
431: self
432: end
# File lib/more/facets/dictionary.rb, line 423
423: def select
424: ary = []
425: each { |k,v| ary << [k,v] if yield k,v }
426: ary
427: end
# File lib/more/facets/dictionary.rb, line 366
366: def shift
367: key = order.first
368: key ? [key,delete(key)] : super
369: end
# File lib/more/facets/dictionary.rb, line 293
293: def store( a,b )
294: @order.push( a ) unless @hash.has_key?( a )
295: @hash.store( a,b )
296: end
# File lib/more/facets/dictionary.rb, line 467
467: def to_a
468: ary = []
469: each { |k,v| ary << [k,v] }
470: ary
471: end
# File lib/more/facets/dictionary.rb, line 371
371: def unshift( k,v )
372: unless @hash.include?( k )
373: @order.unshift( k )
374: @hash.store( k,v )
375: true
376: else
377: false
378: end
379: end