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
Attributes
[RW] order
Public Class methods
[]( *args )
# File lib/facets/more/dictionary.rb, line 77
    def []( *args )
      hsh = new
      if Hash === args[0]
        hsh.replace( args[0] )
      elsif (args.size % 2) != 0
        raise ArgumentError, "odd number of elements for Hash"
      else
        hsh[args.shift] = args.shift while args.size > 0
      end
      hsh
    end
auto( *args )

Alternate to new which auto-creates sub-dictionaries as needed.

  d = Dictionary.auto
  d["a"]["b"]["c"] = "abc"  #=> { "a"=>{"b"=>{"c"=>"abc"}}}
# File lib/facets/more/dictionary.rb, line 134
    def auto( *args )
      leet = lambda { |hsh, key| hsh[key] = new( &leet ) }
      new(*args, &leet)
    end
key_auto()
# File lib/facets/more/dictionary.rb, line 139
    def key_auto
      leet = lambda { |hsh, key| hsh[key] = new( &leet ) }
      new(*args, &leet).order_by{ |k,v| k }
    end
key_new( *args, &block )

Alternate to new which creates a dictionary sorted by key.

  d = Dictionary.key_new
  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 }

An alias alpha is also provided.

# File lib/facets/more/dictionary.rb, line 108
    def key_new( *args, &block )
      new(*args, &block).order_by{ |k,v| k }
    end
new( *args, &blk )
# File lib/facets/more/dictionary.rb, line 148
  def initialize( *args, &blk )
    @order = []
    @order_by = nil
    super
  end
new_by( *args, &blk )

Like new but the block sets the order.

# File lib/facets/more/dictionary.rb, line 91
    def new_by( *args, &blk )
      new(*args).order_by(&blk)
    end
value_new( *args, &block )

Alternate constructor which sorts by value.

  d = Dictionary.value_new
  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/facets/more/dictionary.rb, line 125
    def value_new( *args, &block )
      new(*args, &block).order_by{ |k,v| v }
    end
Public Instance methods
<<(kv)
# File lib/facets/more/dictionary.rb, line 277
  def <<(kv)
    push *kv
  end
==( hsh2 )
# File lib/facets/more/dictionary.rb, line 194
  def ==( hsh2 )
    return false if @order != hsh2.order
    super hsh2
  end
[]=( a,b )

Alias for store

clear()
# File lib/facets/more/dictionary.rb, line 199
  def clear
    @order = []
    super
  end
delete( key )
# File lib/facets/more/dictionary.rb, line 204
  def delete( key )
    @order.delete key
    super
  end
delete_if() {|| ...}
# File lib/facets/more/dictionary.rb, line 227
  def delete_if
    order.clone.each { |k| delete k if yield }
    self
  end
dup()
# File lib/facets/more/dictionary.rb, line 312
  def dup
    self.class[*to_a.flatten]
  end
each() {|k,self[k]| ...}

alias_method :unordered_each, :each

This method is also aliased as each_pair
# File lib/facets/more/dictionary.rb, line 221
  def each
    order.each { |k| yield( k,self[k] ) }
    self
  end
each_key() {|k| ...}
# File lib/facets/more/dictionary.rb, line 209
  def each_key
    order.each { |k| yield( k ) }
    self
  end
each_pair()

Alias for each

each_value() {|self[k]| ...}
# File lib/facets/more/dictionary.rb, line 214
  def each_value
    order.each { |k| yield( self[k] ) }
    self
  end
insert( i,k,v )
# File lib/facets/more/dictionary.rb, line 180
  def insert( i,k,v )
    @order.insert( i,k )
    orig_store( k,v )
  end
inspect()
# File lib/facets/more/dictionary.rb, line 306
  def inspect
    ary = []
    each {|k,v| ary << k.inspect + "=>" + v.inspect}
    '{' + ary.join(", ") + '}'
  end
invert()
# File lib/facets/more/dictionary.rb, line 242
  def invert
    hsh2 = self.class.new
    order.each { |k| hsh2[self[k]] = k }
    hsh2
  end
keys()
# File lib/facets/more/dictionary.rb, line 238
  def keys
    order
  end
merge(hsh2)
# File lib/facets/more/dictionary.rb, line 323
  def merge hsh2
    self.dup.update(hsh2)
  end
merge!( hsh2 )

Alias for update

order()
# File lib/facets/more/dictionary.rb, line 154
  def order
    reorder if @order_by
    @order
  end
order_by( &block )
# File lib/facets/more/dictionary.rb, line 159
  def order_by( &block )
    @order_by = block
    order
    self
  end
pop()
# File lib/facets/more/dictionary.rb, line 291
  def pop
    key = order.last
    key ? [key,delete(key)] : nil
  end
push( k,v )
# File lib/facets/more/dictionary.rb, line 281
  def push( k,v )
    unless self.include? k
      @order.push k
      orig_store(k,v)
      true
    else
      false
    end
  end
reject( &block )
# File lib/facets/more/dictionary.rb, line 248
  def reject( &block )
    self.dup.delete_if &block
  end
reject!( &block )
# File lib/facets/more/dictionary.rb, line 252
  def reject!( &block )
    hsh2 = reject &block
    self == hsh2 ? nil : hsh2
  end
reorder()
# File lib/facets/more/dictionary.rb, line 165
  def reorder
    if @order_by
      assoc = @order.collect{ |k| [k,self[k]] }.sort_by( &@order_by )
      @order = assoc.collect{ |k,v| k }
    end
    @order
  end
replace( hsh2 )
# File lib/facets/more/dictionary.rb, line 257
  def replace( hsh2 )
    @order = hsh2.keys
    super hsh2
  end
select() {|k,v| ...}
# File lib/facets/more/dictionary.rb, line 327
  def select
    ary = []
    each { |k,v| ary << [k,v] if yield k,v }
    ary
  end
shift()
# File lib/facets/more/dictionary.rb, line 262
  def shift
    key = order.first
    key ? [key,delete(key)] : super
  end
store( a,b )
This method is also aliased as []=
# File lib/facets/more/dictionary.rb, line 188
  def store( a,b )
    @order.push( a ) unless has_key? a
    super( a,b )
  end
store_only( a,b )
# File lib/facets/more/dictionary.rb, line 173
  def store_only( a,b )
    store( a,b )
  end
to_a()
# File lib/facets/more/dictionary.rb, line 296
  def to_a
    ary = []
    each { |k,v| ary << [k,v] }
    ary
  end
to_s()
# File lib/facets/more/dictionary.rb, line 302
  def to_s
    self.to_a.to_s
  end
unshift( k,v )
# File lib/facets/more/dictionary.rb, line 267
  def unshift( k,v )
    unless self.include? k
      @order.unshift k
      orig_store(k,v)
      true
    else
      false
    end
  end
update( hsh2 )
This method is also aliased as merge!
# File lib/facets/more/dictionary.rb, line 316
  def update( hsh2 )
    hsh2.each { |k,v| self[k] = v }
    reorder
    self
  end
values()
# File lib/facets/more/dictionary.rb, line 232
  def values
    ary = []
    order.each { |k| ary.push self[k] }
    ary
  end