Class: Hashery::Dictionary
- Includes:
- Enumerable
- Defined in:
- lib/hashery/dictionary.rb
Overview
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 new Dictionary 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.
Class Method Summary collapse
-
.[](*args) ⇒ Dictionary
Create a new Dictionary storing argument pairs as an initial mapping.
-
.alphabetic(*args, &block) ⇒ Object
(also: alpha)
Alternate to #new which creates a dictionary sorted by the key as a string.
-
.auto(*args) ⇒ Object
Alternate to #new which auto-creates sub-dictionaries as needed.
-
.new_by(*args, &blk) ⇒ Object
Like #new but the block sets the order instead of the default.
Instance Method Summary collapse
-
#<<(kv) ⇒ Object
Same as #push.
-
#==(hsh2) ⇒ Object
Is the dictionary instance equivalent to another?.
-
#[](key) ⇒ Object
Lookup entry with key.
-
#[]=(k, i = nil, v = nil) ⇒ Object
Store operator.
-
#clear ⇒ Object
Clear dictionary of all entries.
-
#delete(key) ⇒ Object
Delete the entry with given
key
. -
#delete_if ⇒ Object
Delete entry if it fits conditional block.
-
#dup ⇒ Dictionary
Duplicate dictionary.
-
#each ⇒ Object
(also: #each_pair)
Iterate over each key-value pair.
-
#each_key ⇒ Object
Iterate over each key.
-
#each_value ⇒ Object
Iterate over each value.
-
#empty? ⇒ Boolean
Is the dictionary empty?.
-
#fetch(key, *a, &b) ⇒ Object
Featch entry given
key
. -
#first(x = nil) ⇒ Object
Get/set initial entry value.
-
#has_key?(key) ⇒ Boolean
Does the dictionary have a given
key
. -
#hash_table ⇒ Object
protected
Underlying hash table.
-
#initialize(*args, &blk) ⇒ Dictionary
constructor
New Dictiionary.
-
#insert(index, key, value) ⇒ Object
Insert entry into dictionary at specific index position.
-
#inspect ⇒ String
Inspection string for Dictionary.
-
#invert ⇒ Dictionary
Invert the dictionary.
-
#key?(key) ⇒ Boolean
Does the dictionary have a given
key
. -
#keys ⇒ Array
List of all dictionary keys.
-
#last(x = nil) ⇒ Object
Get/set last entry value.
-
#length ⇒ Object
(also: #size)
Number of items in the dictionary.
-
#merge(hsh2) ⇒ Dictionary
Merge other hash creating new dictionary.
-
#order ⇒ Array
Order of keys.
-
#order_by(&block) ⇒ Object
Keep dictionary sorted by a specific sort order.
-
#order_by_key ⇒ Object
Keep dictionary sorted by key.
-
#order_by_value ⇒ Object
Keep dictionary sorted by value.
-
#pop ⇒ Object
Pop entry off the bottom of dictionary.
-
#push(k, v) ⇒ Object
Push entry on to bottom of the dictionary.
-
#reject(&block) ⇒ Dictionary
Reject entries based on give condition block and return new dictionary.
-
#reject!(&block) ⇒ Hash
Reject entries based on give condition block.
-
#reorder ⇒ Object
Re-apply the sorting procedure.
-
#replace(hsh2) ⇒ Object
Replace dictionary entries with new table.
-
#reverse ⇒ Dictionary
Reverse the order of duplicte dictionary.
-
#reverse! ⇒ Object
Reverse the order of the dictionary.
-
#select ⇒ Array
Select items from dictiornary.
-
#shift ⇒ Object
Remove entry from the to top of dictionary.
-
#store(key, value) ⇒ Object
Add entry into dictionary.
-
#to_a ⇒ Array
Convert to array.
-
#to_h ⇒ Hash
Get a duplicate of the underlying hash table.
-
#to_hash ⇒ Hash
Get a duplicate of the underlying hash table.
-
#to_s ⇒ String
Convert to array then to string.
-
#unshift(k, v) ⇒ Object
Push entry on to the top of dictionary.
-
#update(hsh2) ⇒ Object
(also: #merge!)
Update dictionary with other hash.
-
#values ⇒ Array
List of all dictionary values.
Constructor Details
#initialize(*args, &blk) ⇒ Dictionary
New Dictiionary.
128 129 130 131 132 133 134 135 136 137 138 |
# 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 |
Class Method Details
.[](*args) ⇒ Dictionary
Is this needed? Doesn’t the super class do this?
Create a new Dictionary storing argument pairs as an initial mapping.
67 68 69 70 71 72 73 74 75 76 77 78 79 |
# 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 |
.alphabetic(*args, &block) ⇒ Object Also known as: alpha
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 }
103 104 105 |
# File 'lib/hashery/dictionary.rb', line 103 def alphabetic(*args, &block) new(*args, &block).order_by { |key,value| key.to_s } end |
.auto(*args) ⇒ Object
Alternate to #new which auto-creates sub-dictionaries as needed.
118 119 120 121 122 |
# 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_by(*args, &blk) ⇒ Object
Like #new but the block sets the order instead of the default.
Dictionary.new_by{ |k,v| k }
86 87 88 |
# File 'lib/hashery/dictionary.rb', line 86 def new_by(*args, &blk) new(*args).order_by(&blk) end |
Instance Method Details
#<<(kv) ⇒ Object
Same as #push.
441 442 443 |
# File 'lib/hashery/dictionary.rb', line 441 def <<(kv) push(*kv) end |
#==(hsh2) ⇒ Object
Is the dictionary instance equivalent to another?
232 233 234 235 236 237 238 239 |
# 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 |
#[](key) ⇒ Object
Lookup entry with key.
244 245 246 |
# File 'lib/hashery/dictionary.rb', line 244 def [] key @hash[ key ] end |
#[]=(k, i = nil, v = nil) ⇒ Object
Store operator.
h[key] = value
Or with additional index.
h[key,index] = value
264 265 266 267 268 269 270 |
# 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 ⇒ Object
Clear dictionary of all entries.
299 300 301 302 |
# File 'lib/hashery/dictionary.rb', line 299 def clear @order = [] @hash.clear end |
#delete(key) ⇒ Object
Delete the entry with given key
.
307 308 309 310 |
# File 'lib/hashery/dictionary.rb', line 307 def delete(key) @order.delete(key) @hash.delete(key) end |
#delete_if ⇒ Object
Delete entry if it fits conditional block.
341 342 343 344 |
# File 'lib/hashery/dictionary.rb', line 341 def delete_if order.clone.each { |k| delete k if yield(k,@hash[k]) } self end |
#dup ⇒ Dictionary
Duplicate dictionary.
482 483 484 485 486 |
# File 'lib/hashery/dictionary.rb', line 482 def dup a = [] each{ |k,v| a << k; a << v } self.class[*a] end |
#each ⇒ Object Also known as: each_pair
Iterate over each key-value pair.
331 332 333 334 |
# File 'lib/hashery/dictionary.rb', line 331 def each order.each { |k| yield( k,@hash[k] ) } self end |
#each_key ⇒ Object
Iterate over each key.
315 316 317 318 |
# File 'lib/hashery/dictionary.rb', line 315 def each_key order.each { |k| yield( k ) } self end |
#each_value ⇒ Object
Iterate over each value.
323 324 325 326 |
# File 'lib/hashery/dictionary.rb', line 323 def each_value order.each { |k| yield( @hash[k] ) } self end |
#empty? ⇒ Boolean
Is the dictionary empty?
570 571 572 |
# File 'lib/hashery/dictionary.rb', line 570 def empty? @hash.empty? end |
#fetch(key, *a, &b) ⇒ Object
Featch entry given key
.
251 252 253 |
# File 'lib/hashery/dictionary.rb', line 251 def fetch(key, *a, &b) @hash.fetch(key, *a, &b) end |
#first(x = nil) ⇒ Object
Get/set initial entry value.
543 544 545 546 |
# 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 |
#has_key?(key) ⇒ Boolean
Does the dictionary have a given key
.
579 580 581 |
# File 'lib/hashery/dictionary.rb', line 579 def has_key?(key) @hash.has_key?(key) end |
#hash_table ⇒ Object (protected)
Underlying hash table.
635 636 637 |
# File 'lib/hashery/dictionary.rb', line 635 def hash_table @hash end |
#insert(index, key, value) ⇒ Object
Insert entry into dictionary at specific index position.
281 282 283 284 |
# File 'lib/hashery/dictionary.rb', line 281 def insert(index, key, value) @order.insert(index, key) @hash.store(key, value) end |
#inspect ⇒ String
Inspection string for Dictionary.
471 472 473 474 475 |
# File 'lib/hashery/dictionary.rb', line 471 def inspect ary = [] each {|k,v| ary << k.inspect + "=>" + v.inspect} '{' + ary.join(", ") + '}' end |
#invert ⇒ Dictionary
Invert the dictionary.
371 372 373 374 375 |
# File 'lib/hashery/dictionary.rb', line 371 def invert hsh2 = self.class.new order.each { |k| hsh2[@hash[k]] = k } hsh2 end |
#key?(key) ⇒ Boolean
Does the dictionary have a given key
.
588 589 590 |
# File 'lib/hashery/dictionary.rb', line 588 def key?(key) @hash.key?(key) end |
#keys ⇒ Array
List of all dictionary keys.
362 363 364 |
# File 'lib/hashery/dictionary.rb', line 362 def keys order end |
#last(x = nil) ⇒ Object
Get/set last entry value.
551 552 553 554 |
# 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 |
#length ⇒ Object Also known as: size
Number of items in the dictionary.
559 560 561 |
# File 'lib/hashery/dictionary.rb', line 559 def length @order.length end |
#merge(hsh2) ⇒ Dictionary
Merge other hash creating new dictionary.
506 507 508 |
# File 'lib/hashery/dictionary.rb', line 506 def merge(hsh2) self.dup.update(hsh2) end |
#order ⇒ Array
Order of keys.
145 146 147 148 |
# File 'lib/hashery/dictionary.rb', line 145 def order reorder if @order_by @order end |
#order_by(&block) ⇒ Object
Keep dictionary sorted by a specific sort order.
157 158 159 160 161 |
# File 'lib/hashery/dictionary.rb', line 157 def order_by( &block ) @order_by = block order self end |
#order_by_key ⇒ Object
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.
180 181 182 183 184 185 186 187 188 |
# 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 |
#order_by_value ⇒ Object
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 }
203 204 205 206 207 208 209 210 211 |
# 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 ⇒ Object
Pop entry off the bottom of dictionary.
461 462 463 464 |
# File 'lib/hashery/dictionary.rb', line 461 def pop key = order.last key ? [key,delete(key)] : nil end |
#push(k, v) ⇒ Object
Push entry on to bottom of the dictionary.
448 449 450 451 452 453 454 455 456 |
# 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(&block) ⇒ Dictionary
Reject entries based on give condition block and return new dictionary.
383 384 385 |
# File 'lib/hashery/dictionary.rb', line 383 def reject(&block) self.dup.delete_if(&block) end |
#reject!(&block) ⇒ Hash
Reject entries based on give condition block.
394 395 396 397 |
# File 'lib/hashery/dictionary.rb', line 394 def reject!( &block ) hsh2 = reject(&block) self == hsh2 ? nil : hsh2 end |
#reorder ⇒ Object
Re-apply the sorting procedure.
216 217 218 219 220 221 222 |
# 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(hsh2) ⇒ Object
Replace dictionary entries with new table.
402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
# 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 ⇒ Dictionary
Reverse the order of duplicte dictionary.
536 537 538 |
# File 'lib/hashery/dictionary.rb', line 536 def reverse dup.reverse! end |
#reverse! ⇒ Object
Reverse the order of the dictionary.
526 527 528 529 |
# File 'lib/hashery/dictionary.rb', line 526 def reverse! @order.reverse! self end |
#select ⇒ Array
Select items from dictiornary.
515 516 517 518 519 |
# File 'lib/hashery/dictionary.rb', line 515 def select ary = [] each { |k,v| ary << [k,v] if yield k,v } ary end |
#shift ⇒ Object
Remove entry from the to top of dictionary.
420 421 422 423 |
# File 'lib/hashery/dictionary.rb', line 420 def shift key = order.first key ? [key,delete(key)] : super end |
#store(key, value) ⇒ Object
Add entry into dictionary.
291 292 293 294 |
# File 'lib/hashery/dictionary.rb', line 291 def store(key, value) @order.push(key) unless @hash.has_key?(key) @hash.store(key, value) end |
#to_a ⇒ Array
Convert to array.
597 598 599 600 601 |
# File 'lib/hashery/dictionary.rb', line 597 def to_a ary = [] each { |k,v| ary << [k,v] } ary end |
#to_h ⇒ Hash
Get a duplicate of the underlying hash table.
626 627 628 |
# File 'lib/hashery/dictionary.rb', line 626 def to_h @hash.dup end |
#to_hash ⇒ Hash
Get a duplicate of the underlying hash table.
617 618 619 |
# File 'lib/hashery/dictionary.rb', line 617 def to_hash @hash.dup end |
#to_s ⇒ String
Convert to array then to string.
608 609 610 |
# File 'lib/hashery/dictionary.rb', line 608 def to_s self.to_a.to_s end |
#unshift(k, v) ⇒ Object
Push entry on to the top of dictionary.
428 429 430 431 432 433 434 435 436 |
# 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(hsh2) ⇒ Object Also known as: merge!
Update dictionary with other hash.
493 494 495 496 497 |
# File 'lib/hashery/dictionary.rb', line 493 def update( hsh2 ) hsh2.each { |k,v| self[k] = v } reorder self end |
#values ⇒ Array
List of all dictionary values.
351 352 353 354 355 |
# File 'lib/hashery/dictionary.rb', line 351 def values ary = [] order.each { |k| ary.push @hash[k] } ary end |