Class Dictionary
In: lib/more/facets/dictionary.rb
Parent: Object

Dictionary

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.

Usage

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

Usage Notes

  • You can use order_by to set internal sort order.
  • #<< takes a two element [k,v] array and inserts.
  • Use ::auto which creates Dictionay sub-entries as needed.
  • And ::alpha which creates a new Dictionary sorted by key.

Methods

<<   ==   []   []   []=   alpha   auto   clear   delete   delete_if   dup   each   each_key   each_pair   each_value   empty?   fetch   first   has_key?   insert   inspect   invert   key?   keys   last   length   merge   merge!   new   new_by   order   order_by   order_by_key   order_by_value   pop   push   reject   reject!   reorder   replace   reverse   reverse!   select   shift   size   store   to_a   to_h   to_hash   to_s   unshift   update   values  

Included Modules

Enumerable

Public Class methods

[Source]

     # 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 }

[Source]

     # 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"}}}

[Source]

     # 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.

[Source]

     # 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

Like new but the block sets the order.

[Source]

     # File lib/more/facets/dictionary.rb, line 144
144:     def new_by(*args, &blk)
145:       new(*args).order_by(&blk)
146:     end

Public Instance methods

[Source]

     # File lib/more/facets/dictionary.rb, line 381
381:   def <<(kv)
382:     push(*kv)
383:   end

def ==( hsh2 )

  return false if @order != hsh2.order
  super hsh2

end

[Source]

     # 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

[Source]

     # File lib/more/facets/dictionary.rb, line 264
264:   def [] k
265:     @hash[ k ]
266:   end

Store operator.

  h[key] = value

Or with additional index.

 h[key,index] = value

[Source]

     # 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

[Source]

     # File lib/more/facets/dictionary.rb, line 298
298:   def clear
299:     @order = []
300:     @hash.clear
301:   end

[Source]

     # File lib/more/facets/dictionary.rb, line 303
303:   def delete( key )
304:     @order.delete( key )
305:     @hash.delete( key )
306:   end

[Source]

     # 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

[Source]

     # 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

[Source]

     # File lib/more/facets/dictionary.rb, line 318
318:   def each
319:     order.each { |k| yield( k,@hash[k] ) }
320:     self
321:   end

[Source]

     # File lib/more/facets/dictionary.rb, line 308
308:   def each_key
309:     order.each { |k| yield( k ) }
310:     self
311:   end
each_pair()

Alias for each

[Source]

     # File lib/more/facets/dictionary.rb, line 313
313:   def each_value
314:     order.each { |k| yield( @hash[k] ) }
315:     self
316:   end

[Source]

     # File lib/more/facets/dictionary.rb, line 455
455:   def empty?
456:     @hash.empty?
457:   end

[Source]

     # File lib/more/facets/dictionary.rb, line 268
268:   def fetch(k, *a, &b)
269:     @hash.fetch(k, *a, &b)
270:   end

[Source]

     # 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

[Source]

     # File lib/more/facets/dictionary.rb, line 459
459:   def has_key?(key)
460:     @hash.has_key?(key)
461:   end

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # File lib/more/facets/dictionary.rb, line 463
463:   def key?(key)
464:     @hash.key?(key)
465:   end

[Source]

     # File lib/more/facets/dictionary.rb, line 335
335:   def keys
336:     order
337:   end

[Source]

     # 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

[Source]

     # File lib/more/facets/dictionary.rb, line 450
450:   def length
451:     @order.length
452:   end

[Source]

     # File lib/more/facets/dictionary.rb, line 419
419:   def merge( hsh2 )
420:     self.dup.update(hsh2)
421:   end
merge!( hsh2 )

Alias for update

[Source]

     # File lib/more/facets/dictionary.rb, line 190
190:   def order
191:     reorder if @order_by
192:     @order
193:   end

Keep dictionary sorted by a specific sort order.

[Source]

     # File lib/more/facets/dictionary.rb, line 197
197:   def order_by( &block )
198:     @order_by = block
199:     order
200:     self
201:   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.

[Source]

     # 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 }

[Source]

     # 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

[Source]

     # File lib/more/facets/dictionary.rb, line 395
395:   def pop
396:     key = order.last
397:     key ? [key,delete(key)] : nil
398:   end

[Source]

     # 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

[Source]

     # File lib/more/facets/dictionary.rb, line 345
345:   def reject(&block)
346:     self.dup.delete_if(&block)
347:   end

[Source]

     # File lib/more/facets/dictionary.rb, line 349
349:   def reject!( &block )
350:     hsh2 = reject(&block)
351:     self == hsh2 ? nil : hsh2
352:   end

[Source]

     # 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

[Source]

     # 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

[Source]

     # File lib/more/facets/dictionary.rb, line 434
434:   def reverse
435:     dup.reverse!
436:   end

[Source]

     # File lib/more/facets/dictionary.rb, line 429
429:   def reverse!
430:     @order.reverse!
431:     self
432:   end

[Source]

     # 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

[Source]

     # File lib/more/facets/dictionary.rb, line 366
366:   def shift
367:     key = order.first
368:     key ? [key,delete(key)] : super
369:   end
size()

Alias for length

[Source]

     # 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

[Source]

     # 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

[Source]

     # File lib/more/facets/dictionary.rb, line 481
481:   def to_h
482:     @hash.dup
483:   end

[Source]

     # File lib/more/facets/dictionary.rb, line 477
477:   def to_hash
478:     @hash.dup
479:   end

[Source]

     # File lib/more/facets/dictionary.rb, line 473
473:   def to_s
474:     self.to_a.to_s
475:   end

[Source]

     # 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

[Source]

     # File lib/more/facets/dictionary.rb, line 412
412:   def update( hsh2 )
413:     hsh2.each { |k,v| self[k] = v }
414:     reorder
415:     self
416:   end

[Source]

     # File lib/more/facets/dictionary.rb, line 329
329:   def values
330:     ary = []
331:     order.each { |k| ary.push @hash[k] }
332:     ary
333:   end

[Validate]