Class: Aequitas::OrderedHash
- Inherits:
-
Object
- Object
- Aequitas::OrderedHash
- Includes:
- Enumerable
- Defined in:
- lib/aequitas/support/ordered_hash.rb
Overview
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 doesn'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.
Class Method Summary collapse
-
.[](*args) ⇒ Object
– TODO is this needed? Doesn’t the super class do this? ++.
-
.alpha(*args, &block) ⇒ Object
Alternate to #new which creates a dictionary sorted by key.
-
.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.
Instance Method Summary collapse
- #<<(kv) ⇒ Object
- #==(hsh2) ⇒ Object
- #[](k) ⇒ Object
-
#[]=(k, i = nil, v = nil) ⇒ Object
Store operator.
- #clear ⇒ Object
- #delete(key) ⇒ Object
- #delete_if ⇒ Object
- #dup ⇒ Object
- #each ⇒ Object (also: #each_pair)
- #each_key ⇒ Object
- #each_value ⇒ Object
- #empty? ⇒ Boolean
- #fetch(k, *a, &b) ⇒ Object
- #first ⇒ Object
- #has_key?(key) ⇒ Boolean
-
#initialize(*args, &blk) ⇒ OrderedHash
constructor
New Dictiionary.
- #insert(i, k, v) ⇒ Object
- #inspect ⇒ Object
- #invert ⇒ Object
- #key?(key) ⇒ Boolean
- #keys ⇒ Object
- #last ⇒ Object
- #length ⇒ Object (also: #size)
- #merge(hsh2) ⇒ Object
- #order ⇒ Object
-
#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
- #push(k, v) ⇒ Object
- #reject(&block) ⇒ Object
- #reject!(&block) ⇒ Object
- #reorder ⇒ Object
- #replace(hsh2) ⇒ Object
- #reverse ⇒ Object
- #reverse! ⇒ Object
- #select ⇒ Object
- #shift ⇒ Object
- #store(a, b) ⇒ Object
- #to_a ⇒ Object
- #to_h ⇒ Object
- #to_hash ⇒ Object
- #to_json ⇒ Object
- #to_s ⇒ Object
- #unshift(k, v) ⇒ Object
- #update(hsh2) ⇒ Object (also: #merge!)
- #values ⇒ Object
Constructor Details
#initialize(*args, &blk) ⇒ OrderedHash
New Dictiionary.
139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/aequitas/support/ordered_hash.rb', line 139 def initialize(*args, &blk) @order = [] @order_by = nil if blk dict = self # This ensure autmatic 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) ⇒ Object
– TODO is this needed? Doesn’t the super class do this? ++
91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/aequitas/support/ordered_hash.rb', line 91 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 |
.alpha(*args, &block) ⇒ Object
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 }
122 123 124 |
# File 'lib/aequitas/support/ordered_hash.rb', line 122 def alpha(*args, &block) new(*args, &block).order_by_key end |
.auto(*args) ⇒ Object
Alternate to #new which auto-creates sub-dictionaries as needed.
d = Dictionary.auto
d["a"]["b"]["c"] = "abc" #=> { "a"=>{"b"=>{"c"=>"abc"}}}
131 132 133 134 135 |
# File 'lib/aequitas/support/ordered_hash.rb', line 131 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.
107 108 109 |
# File 'lib/aequitas/support/ordered_hash.rb', line 107 def new_by(*args, &blk) new(*args).order_by(&blk) end |
Instance Method Details
#<<(kv) ⇒ Object
326 327 328 |
# File 'lib/aequitas/support/ordered_hash.rb', line 326 def <<(kv) push( *kv ) end |
#==(hsh2) ⇒ Object
208 209 210 211 212 213 214 215 |
# File 'lib/aequitas/support/ordered_hash.rb', line 208 def ==(hsh2) if hsh2.is_a?( Dictionary ) @order == hsh2.order && @hash == hsh2.instance_variable_get("@hash") else false end end |
#[](k) ⇒ Object
217 218 219 |
# File 'lib/aequitas/support/ordered_hash.rb', line 217 def [] k @hash[ k ] end |
#[]=(k, i = nil, v = nil) ⇒ Object
Store operator.
h[key] = value
Or with additional index.
h[key,index] = value
232 233 234 235 236 237 238 |
# File 'lib/aequitas/support/ordered_hash.rb', line 232 def []=(k, i=nil, v=nil) if v insert(i,k,v) else store(k,i) end end |
#clear ⇒ Object
250 251 252 253 |
# File 'lib/aequitas/support/ordered_hash.rb', line 250 def clear @order = [] @hash.clear end |
#delete(key) ⇒ Object
255 256 257 258 |
# File 'lib/aequitas/support/ordered_hash.rb', line 255 def delete( key ) @order.delete( key ) @hash.delete( key ) end |
#delete_if ⇒ Object
276 277 278 279 |
# File 'lib/aequitas/support/ordered_hash.rb', line 276 def delete_if order.clone.each { |k| delete k if yield(k,@hash[k]) } self end |
#dup ⇒ Object
351 352 353 354 355 |
# File 'lib/aequitas/support/ordered_hash.rb', line 351 def dup a = [] each{ |k,v| a << k; a << v } self.class[*a] end |
#each ⇒ Object Also known as: each_pair
270 271 272 273 |
# File 'lib/aequitas/support/ordered_hash.rb', line 270 def each order.each { |k| yield( k,@hash[k] ) } self end |
#each_key ⇒ Object
260 261 262 263 |
# File 'lib/aequitas/support/ordered_hash.rb', line 260 def each_key order.each { |k| yield( k ) } self end |
#each_value ⇒ Object
265 266 267 268 |
# File 'lib/aequitas/support/ordered_hash.rb', line 265 def each_value order.each { |k| yield( @hash[k] ) } self end |
#empty? ⇒ Boolean
396 397 398 |
# File 'lib/aequitas/support/ordered_hash.rb', line 396 def empty? @hash.empty? end |
#fetch(k, *a, &b) ⇒ Object
221 222 223 |
# File 'lib/aequitas/support/ordered_hash.rb', line 221 def fetch(k, *a, &b) @hash.fetch(k, *a, &b) end |
#first ⇒ Object
383 384 385 |
# File 'lib/aequitas/support/ordered_hash.rb', line 383 def first @hash[order.first] end |
#has_key?(key) ⇒ Boolean
400 401 402 |
# File 'lib/aequitas/support/ordered_hash.rb', line 400 def has_key?(key) @hash.has_key?(key) end |
#insert(i, k, v) ⇒ Object
240 241 242 243 |
# File 'lib/aequitas/support/ordered_hash.rb', line 240 def insert( i,k,v ) @order.insert( i,k ) @hash.store( k,v ) end |
#inspect ⇒ Object
345 346 347 348 349 |
# File 'lib/aequitas/support/ordered_hash.rb', line 345 def inspect ary = [] each {|k,v| ary << k.inspect + "=>" + v.inspect} '{' + ary.join(", ") + '}' end |
#invert ⇒ Object
291 292 293 294 295 |
# File 'lib/aequitas/support/ordered_hash.rb', line 291 def invert hsh2 = self.class.new order.each { |k| hsh2[@hash[k]] = k } hsh2 end |
#key?(key) ⇒ Boolean
404 405 406 |
# File 'lib/aequitas/support/ordered_hash.rb', line 404 def key?(key) @hash.key?(key) end |
#keys ⇒ Object
287 288 289 |
# File 'lib/aequitas/support/ordered_hash.rb', line 287 def keys order end |
#last ⇒ Object
387 388 389 |
# File 'lib/aequitas/support/ordered_hash.rb', line 387 def last @hash[order.last] end |
#length ⇒ Object Also known as: size
391 392 393 |
# File 'lib/aequitas/support/ordered_hash.rb', line 391 def length @order.length end |
#merge(hsh2) ⇒ Object
364 365 366 |
# File 'lib/aequitas/support/ordered_hash.rb', line 364 def merge( hsh2 ) self.dup.update(hsh2) end |
#order ⇒ Object
151 152 153 154 |
# File 'lib/aequitas/support/ordered_hash.rb', line 151 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/aequitas/support/ordered_hash.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.
176 177 178 179 180 |
# File 'lib/aequitas/support/ordered_hash.rb', line 176 def order_by_key @order_by = lambda { |k,v| k } 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 }
193 194 195 196 197 |
# File 'lib/aequitas/support/ordered_hash.rb', line 193 def order_by_value @order_by = lambda { |k,v| v } order self end |
#pop ⇒ Object
340 341 342 343 |
# File 'lib/aequitas/support/ordered_hash.rb', line 340 def pop key = order.last key ? [key,delete(key)] : nil end |
#push(k, v) ⇒ Object
330 331 332 333 334 335 336 337 338 |
# File 'lib/aequitas/support/ordered_hash.rb', line 330 def push( k,v ) unless @hash.include?( k ) @order.push( k ) @hash.store( k,v ) true else false end end |
#reject(&block) ⇒ Object
297 298 299 |
# File 'lib/aequitas/support/ordered_hash.rb', line 297 def reject( &block ) self.dup.delete_if(&block) end |
#reject!(&block) ⇒ Object
301 302 303 304 |
# File 'lib/aequitas/support/ordered_hash.rb', line 301 def reject!( &block ) hsh2 = reject(&block) self == hsh2 ? nil : hsh2 end |
#reorder ⇒ Object
200 201 202 203 204 205 206 |
# File 'lib/aequitas/support/ordered_hash.rb', line 200 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
306 307 308 309 |
# File 'lib/aequitas/support/ordered_hash.rb', line 306 def replace( hsh2 ) @order = hsh2.order @hash = hsh2.hash end |
#reverse ⇒ Object
379 380 381 |
# File 'lib/aequitas/support/ordered_hash.rb', line 379 def reverse dup.reverse! end |
#reverse! ⇒ Object
374 375 376 377 |
# File 'lib/aequitas/support/ordered_hash.rb', line 374 def reverse! @order.reverse! self end |
#select ⇒ Object
368 369 370 371 372 |
# File 'lib/aequitas/support/ordered_hash.rb', line 368 def select ary = [] each { |k,v| ary << [k,v] if yield k,v } ary end |
#shift ⇒ Object
311 312 313 314 |
# File 'lib/aequitas/support/ordered_hash.rb', line 311 def shift key = order.first key ? [key,delete(key)] : super end |
#store(a, b) ⇒ Object
245 246 247 248 |
# File 'lib/aequitas/support/ordered_hash.rb', line 245 def store( a,b ) @order.push( a ) unless @hash.has_key?( a ) @hash.store( a,b ) end |
#to_a ⇒ Object
408 409 410 411 412 |
# File 'lib/aequitas/support/ordered_hash.rb', line 408 def to_a ary = [] each { |k,v| ary << [k,v] } ary end |
#to_h ⇒ Object
433 434 435 |
# File 'lib/aequitas/support/ordered_hash.rb', line 433 def to_h @hash.dup end |
#to_hash ⇒ Object
429 430 431 |
# File 'lib/aequitas/support/ordered_hash.rb', line 429 def to_hash @hash.dup end |
#to_json ⇒ Object
414 415 416 417 418 419 420 421 422 423 |
# File 'lib/aequitas/support/ordered_hash.rb', line 414 def to_json buf = "[" map do |k,v| buf << k.to_json buf << ", " buf << v.to_json end.join(", ") buf << "]" buf end |
#to_s ⇒ Object
425 426 427 |
# File 'lib/aequitas/support/ordered_hash.rb', line 425 def to_s self.to_a.to_s end |
#unshift(k, v) ⇒ Object
316 317 318 319 320 321 322 323 324 |
# File 'lib/aequitas/support/ordered_hash.rb', line 316 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!
357 358 359 360 361 |
# File 'lib/aequitas/support/ordered_hash.rb', line 357 def update( hsh2 ) hsh2.each { |k,v| self[k] = v } reorder self end |
#values ⇒ Object
281 282 283 284 285 |
# File 'lib/aequitas/support/ordered_hash.rb', line 281 def values ary = [] order.each { |k| ary.push @hash[k] } ary end |