class Hashery::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.
Using a Dictionary
is almost the same as using a 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
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 newDictionary
sorted by key.
Acknowledgments¶ ↑
Dictionary
is a port of OrderHash 2.0 Copyright © 2005 Jan Molic.
People who have contributed to this class since then include:
-
Andrew Johnson (merge,
to_a
, inspect, shift and Hash[]) -
Jeff Sharpe (reverse and reverse!)
-
Thomas Leitner (has_key? and key?)
OrderedHash
is public domain.
Public Class Methods
Create a new Dictionary
storing argument pairs as an initial mapping.
TODO: Is this needed? Doesn't the super class do this?
Returns Dictionary
instance.
# File lib/hashery/dictionary.rb, line 67 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 while !args.empty? hsh[args.shift] = args.shift end end hsh end
Alternate to new which creates a dictionary sorted by the key as a string.
d = Dictionary.alphabetic 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.to_s }
# File lib/hashery/dictionary.rb, line 103 def alphabetic(*args, &block) new(*args, &block).order_by { |key,value| key.to_s } end
Alternate to new which auto-creates sub-dictionaries as needed.
Examples
d = Dictionary.auto d["a"]["b"]["c"] = "abc" #=> { "a"=>{"b"=>{"c"=>"abc"}}}
# File lib/hashery/dictionary.rb, line 118 def auto(*args) #AutoDictionary.new(*args) leet = lambda { |hsh, key| hsh[key] = new(&leet) } new(*args, &leet) end
New Dictiionary.
# File lib/hashery/dictionary.rb, line 128 def initialize(*args, &blk) @order = [] @order_by = nil if blk dict = self # This ensures automatic key entry effect the oblk = lambda{ |hsh, key| blk[dict,key] } # dictionary rather then just the interal hash. @hash = Hash.new(*args, &oblk) else @hash = Hash.new(*args) end end
Like new but the block sets the order instead of the default.
Dictionary.new_by{ |k,v| k }
# File lib/hashery/dictionary.rb, line 86 def new_by(*args, &blk) new(*args).order_by(&blk) end
Public Instance Methods
Same as push
.
# File lib/hashery/dictionary.rb, line 441 def <<(kv) push(*kv) end
Is the dictionary instance equivalent to another?
# File lib/hashery/dictionary.rb, line 232 def ==(hsh2) if hsh2.is_a?( Dictionary ) @order == hsh2.order && @hash == hsh2.instance_variable_get("@hash") else false end end
Lookup entry with key.
# File lib/hashery/dictionary.rb, line 244 def [] key @hash[ key ] end
Store operator.
h[key] = value
Or with additional index.
h[key,index] = value
# File lib/hashery/dictionary.rb, line 264 def []=(k, i=nil, v=nil) if v insert(i,k,v) else store(k,i) end end
Clear dictionary of all entries.
# File lib/hashery/dictionary.rb, line 299 def clear @order = [] @hash.clear end
Delete the entry with given key
.
# File lib/hashery/dictionary.rb, line 307 def delete(key) @order.delete(key) @hash.delete(key) end
Delete entry if it fits conditional block.
# File lib/hashery/dictionary.rb, line 341 def delete_if order.clone.each { |k| delete k if yield(k,@hash[k]) } self end
Duplicate dictionary.
Returns [Dictionary].
# File lib/hashery/dictionary.rb, line 482 def dup a = [] each{ |k,v| a << k; a << v } self.class[*a] end
Iterate over each key-value pair.
# File lib/hashery/dictionary.rb, line 331 def each order.each { |k| yield( k,@hash[k] ) } self end
Iterate over each key.
# File lib/hashery/dictionary.rb, line 315 def each_key order.each { |k| yield( k ) } self end
Iterate over each value.
# File lib/hashery/dictionary.rb, line 323 def each_value order.each { |k| yield( @hash[k] ) } self end
Is the dictionary empty?
Returns `true` or `false`.
# File lib/hashery/dictionary.rb, line 570 def empty? @hash.empty? end
Featch entry given key
.
# File lib/hashery/dictionary.rb, line 251 def fetch(key, *a, &b) @hash.fetch(key, *a, &b) end
Get/set initial entry value.
# File lib/hashery/dictionary.rb, line 543 def first(x=nil) return @hash[order.first] unless x order.first(x).collect { |k| @hash[k] } end
Does the dictionary have a given key
.
Returns `true` or `false`.
# File lib/hashery/dictionary.rb, line 579 def has_key?(key) @hash.has_key?(key) end
Insert entry into dictionary at specific index position.
index - [Integer] Position of order placement. key - [Object] Key to associate with value. value - [Object] Value to associate with key.
Returns `value` stored.
# File lib/hashery/dictionary.rb, line 281 def insert(index, key, value) @order.insert(index, key) @hash.store(key, value) end
Inspection string for Dictionary
.
Returns [String].
# File lib/hashery/dictionary.rb, line 471 def inspect ary = [] each {|k,v| ary << k.inspect + "=>" + v.inspect} '{' + ary.join(", ") + '}' end
Invert the dictionary.
Returns [Dictionary] New dictionary that is inverse of the original.
# File lib/hashery/dictionary.rb, line 371 def invert hsh2 = self.class.new order.each { |k| hsh2[@hash[k]] = k } hsh2 end
Does the dictionary have a given key
.
Returns `true` or `false`.
# File lib/hashery/dictionary.rb, line 588 def key?(key) @hash.key?(key) end
List of all dictionary keys.
Returns [Array].
# File lib/hashery/dictionary.rb, line 362 def keys order end
Get/set last entry value.
# File lib/hashery/dictionary.rb, line 551 def last(x=nil) return @hash[order.last] unless x order.last(x).collect { |k| @hash[k] } end
Number of items in the dictionary.
# File lib/hashery/dictionary.rb, line 559 def length @order.length end
Merge other hash creating new dictionary.
Returns [Dictionary].
# File lib/hashery/dictionary.rb, line 506 def merge(hsh2) self.dup.update(hsh2) end
Order of keys.
Returns [Array].
# File lib/hashery/dictionary.rb, line 145 def order reorder if @order_by @order end
Keep dictionary sorted by a specific sort order.
block - Ordering procedure.
Returns self
.
# File lib/hashery/dictionary.rb, line 157 def order_by( &block ) @order_by = block order self 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.
Returns self
.
# File lib/hashery/dictionary.rb, line 180 def order_by_key if block_given? @order_by = Proc.new{ |k,v| yield(k) } else @order_by = Proc.new{ |k,v| k } end order self 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/hashery/dictionary.rb, line 203 def order_by_value if block_given? @order_by = Proc.new{ |k,v| yield(v) } else @order_by = Proc.new{ |k,v| v } end order self end
Pop entry off the bottom of dictionary.
# File lib/hashery/dictionary.rb, line 461 def pop key = order.last key ? [key,delete(key)] : nil end
Push entry on to bottom of the dictionary.
# File lib/hashery/dictionary.rb, line 448 def push(k,v) unless @hash.include?( k ) @order.push( k ) @hash.store( k,v ) true else false end end
Reject entries based on give condition block and return new dictionary.
Returns [Dictionary].
# File lib/hashery/dictionary.rb, line 383 def reject(&block) self.dup.delete_if(&block) end
Reject entries based on give condition block.
Returns [Hash] of rejected entries.
FIXME: This looks like it is implemented wrong!!!
# File lib/hashery/dictionary.rb, line 394 def reject!( &block ) hsh2 = reject(&block) self == hsh2 ? nil : hsh2 end
Re-apply the sorting procedure.
# File lib/hashery/dictionary.rb, line 216 def reorder if @order_by assoc = @order.collect{ |k| [k,@hash[k]] }.sort_by(&@order_by) @order = assoc.collect{ |k,v| k } end @order end
Replace dictionary entries with new table.
# File lib/hashery/dictionary.rb, line 402 def replace(hsh2) case hsh2 when Dictionary @order = hsh2.order @hash = hsh2.to_h when Hash @hash = hsh2 @order = @hash.keys else @hash = hsh2.to_h @order = @hash.keys end reorder end
Reverse the order of duplicte dictionary.
Returns [Dictionary].
# File lib/hashery/dictionary.rb, line 536 def reverse dup.reverse! end
Reverse the order of the dictionary.
Returns self.
# File lib/hashery/dictionary.rb, line 526 def reverse! @order.reverse! self end
Select items from dictiornary.
Returns [Array] of two-element arrays.
# File lib/hashery/dictionary.rb, line 515 def select ary = [] each { |k,v| ary << [k,v] if yield k,v } ary end
Remove entry from the to top of dictionary.
# File lib/hashery/dictionary.rb, line 420 def shift key = order.first key ? [key,delete(key)] : super end
Add entry into dictionary.
Returns `value`.
# File lib/hashery/dictionary.rb, line 291 def store(key, value) @order.push(key) unless @hash.has_key?(key) @hash.store(key, value) end
Convert to array.
Returns [Array] of two-element arrays.
# File lib/hashery/dictionary.rb, line 597 def to_a ary = [] each { |k,v| ary << [k,v] } ary end
Get a duplicate of the underlying hash table.
Returns [Hash].
# File lib/hashery/dictionary.rb, line 626 def to_h @hash.dup end
Get a duplicate of the underlying hash table.
Returns [Hash].
# File lib/hashery/dictionary.rb, line 617 def to_hash @hash.dup end
Convert to array then to string.
Returns [String].
# File lib/hashery/dictionary.rb, line 608 def to_s self.to_a.to_s end
Push entry on to the top of dictionary.
# File lib/hashery/dictionary.rb, line 428 def unshift( k,v ) unless @hash.include?( k ) @order.unshift( k ) @hash.store( k,v ) true else false end end
Update dictionary with other hash.
Returns self.
# File lib/hashery/dictionary.rb, line 493 def update( hsh2 ) hsh2.each { |k,v| self[k] = v } reorder self end
List of all dictionary values.
Returns [Array].
# File lib/hashery/dictionary.rb, line 351 def values ary = [] order.each { |k| ary.push @hash[k] } ary end
Protected Instance Methods
Underlying hash table.
# File lib/hashery/dictionary.rb, line 635 def hash_table @hash end