hashery 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/HISTORY +15 -0
- data/LICENSE +23 -0
- data/README.rdoc +47 -0
- data/ROADMAP.rdoc +13 -0
- data/lib/hashery.rb +13 -0
- data/lib/hashery/castinghash.rb +171 -0
- data/lib/hashery/dictionary.rb +430 -0
- data/lib/hashery/lruhash.rb +274 -0
- data/lib/hashery/memoizer.rb +64 -0
- data/lib/hashery/opencascade.rb +82 -0
- data/lib/hashery/openhash.rb +65 -0
- data/lib/hashery/openobject.rb +279 -0
- data/lib/hashery/orderedhash.rb +417 -0
- data/lib/hashery/ostructable.rb +209 -0
- data/lib/hashery/queryhash.rb +35 -0
- data/lib/hashery/stash.rb +181 -0
- data/lib/hashery/statichash.rb +48 -0
- data/meta/authors +3 -0
- data/meta/created +1 -0
- data/meta/description +5 -0
- data/meta/homepage +1 -0
- data/meta/license +1 -0
- data/meta/name +1 -0
- data/meta/release +1 -0
- data/meta/repository +1 -0
- data/meta/suite +1 -0
- data/meta/summary +1 -0
- data/meta/version +1 -0
- data/test/case_dictionary.rb +142 -0
- data/test/case_opencascade.rb +68 -0
- data/test/case_openhash.rb +18 -0
- data/test/case_openobject.rb +130 -0
- data/test/case_stash.rb +131 -0
- metadata +102 -0
data/HISTORY
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
== 1.0.0 // 2010-04-21
|
2
|
+
|
3
|
+
This is the first release of the Facets Hashery.
|
4
|
+
Most of included classes come directly from Ruby
|
5
|
+
Facets, so they have been around a while and are
|
6
|
+
in good working condition.
|
7
|
+
|
8
|
+
Some improvements are planned for the next release.
|
9
|
+
In particular the OrderHash and Dictionary, which
|
10
|
+
presently have essentially the same coding, will
|
11
|
+
diverge to target slightly different use cases.
|
12
|
+
|
13
|
+
Changes:
|
14
|
+
|
15
|
+
* Happy Birthday!
|
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2005 Thomas Sawyer
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
22
|
+
|
23
|
+
|
data/README.rdoc
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
= Facets Hashery
|
2
|
+
|
3
|
+
* home: http://rubyworks.github.com/hashery
|
4
|
+
* work: http://github.com/rubyworks/hashery
|
5
|
+
|
6
|
+
== DESCRIPTION
|
7
|
+
|
8
|
+
Among Ruby Facets most common additions were an assortment
|
9
|
+
of Hash-like classes. To better support this collection of
|
10
|
+
of libraries it was deemed prudent to create a side project
|
11
|
+
specifically for them. Hence the Facets Hashery.
|
12
|
+
|
13
|
+
Included in this collect are the widely used OrderedHash,
|
14
|
+
the related but more featured Dictionary class, a number
|
15
|
+
of _open_ classes, similiar to the standard OpenStruct,
|
16
|
+
and variations of the standard Hash.
|
17
|
+
|
18
|
+
|
19
|
+
== RELEASE NOTES
|
20
|
+
|
21
|
+
Please see the HISTORY file.
|
22
|
+
|
23
|
+
|
24
|
+
== HOW TO USE
|
25
|
+
|
26
|
+
For usage information, see the individual library files include
|
27
|
+
in this collection.
|
28
|
+
|
29
|
+
|
30
|
+
== HOW TO INSTALL
|
31
|
+
|
32
|
+
To install with RubyGems simply open a console and type:
|
33
|
+
|
34
|
+
$ sudo gem install hashery
|
35
|
+
|
36
|
+
Tarball packages are available for manual site installations
|
37
|
+
via <a href="http://proutils.github.com/setup">Setup.rb</a>.
|
38
|
+
|
39
|
+
|
40
|
+
== LICENSE
|
41
|
+
|
42
|
+
Copyright (c) 2005,2010 Thomas Sawyer
|
43
|
+
|
44
|
+
This program is ditributed unser the terms of the MIT license.
|
45
|
+
|
46
|
+
See LICENSE file for details.
|
47
|
+
|
data/ROADMAP.rdoc
ADDED
data/lib/hashery.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'hashery/castinghash'
|
2
|
+
require 'hashery/dictionary'
|
3
|
+
require 'hashery/lruhash'
|
4
|
+
require 'hashery/memoizer'
|
5
|
+
require 'hashery/opencascade'
|
6
|
+
require 'hashery/openhash'
|
7
|
+
require 'hashery/openobject'
|
8
|
+
require 'hashery/orderedhash'
|
9
|
+
require 'hashery/ostructable'
|
10
|
+
require 'hashery/queryhash'
|
11
|
+
require 'hashery/stash'
|
12
|
+
require 'hashery/statichash'
|
13
|
+
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# CastingHash is just like Hash, except that all keys and values
|
2
|
+
# are passed through casting procedures.
|
3
|
+
#--
|
4
|
+
# TODO: Handle default_proc.
|
5
|
+
#++
|
6
|
+
class CastingHash < Hash
|
7
|
+
|
8
|
+
# Default key conversion procedure.
|
9
|
+
KEY_PROC = lambda{ |x| x } #.to_s }
|
10
|
+
|
11
|
+
# Default value conversion procedure.
|
12
|
+
VAL_PROC = lambda{ |x| x }
|
13
|
+
|
14
|
+
#
|
15
|
+
def self.[](hash)
|
16
|
+
s = new
|
17
|
+
hash.each{ |k,v| s[k] = v }
|
18
|
+
s
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
def initialize(hash={}, value_cast=nil, &key_cast)
|
23
|
+
@key_proc = key_cast || KEY_PROC
|
24
|
+
@value_proc = value_cast.to_proc || VAL_PROC
|
25
|
+
hash.each{ |k,v| self[k] = v }
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
def key_proc
|
30
|
+
@key_proc
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
def key_proc=(proc)
|
35
|
+
@key_proc = proc.to_proc
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
def value_proc
|
40
|
+
@value_proc
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
def value_proc=(proc)
|
45
|
+
@value_proc = proc.to_proc
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
def [](k)
|
50
|
+
super(key_proc[k])
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
def []=(k,v)
|
55
|
+
super(key_proc[k], value_proc[v])
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
def <<(other)
|
60
|
+
case other
|
61
|
+
when Hash
|
62
|
+
super(cast(other))
|
63
|
+
when Array
|
64
|
+
self[other[0]] = other[1]
|
65
|
+
else
|
66
|
+
raise ArgumentError
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def fetch(k)
|
71
|
+
super(key_proc[k])
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
def store(k, v)
|
76
|
+
super(key_proc[k], value_proc[v])
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
def key?(k)
|
81
|
+
super(key_proc[k])
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
def has_key?(k)
|
86
|
+
super(key_proc[k])
|
87
|
+
end
|
88
|
+
|
89
|
+
# Synonym for Hash#rekey, but modifies the receiver in place (and returns it).
|
90
|
+
#
|
91
|
+
# foo = { :name=>'Gavin', :wife=>:Lisa }.to_stash
|
92
|
+
# foo.rekey!{ |k| k.upcase } #=> { "NAME"=>"Gavin", "WIFE"=>:Lisa }
|
93
|
+
# foo.inspect #=> { "NAME"=>"Gavin", "WIFE"=>:Lisa }
|
94
|
+
#
|
95
|
+
def rekey!(*args, &block)
|
96
|
+
# for backward comptability (DEPRECATE?).
|
97
|
+
block = args.pop.to_sym.to_proc if args.size == 1
|
98
|
+
if args.empty?
|
99
|
+
block = lambda{|k| k} unless block
|
100
|
+
keys.each do |k|
|
101
|
+
nk = block[k]
|
102
|
+
self[nk] = delete(k) #if nk
|
103
|
+
end
|
104
|
+
else
|
105
|
+
raise ArgumentError, "3 for 2" if block
|
106
|
+
to, from = *args
|
107
|
+
self[to] = delete(from) if has_key?(from)
|
108
|
+
end
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
def rekey(*args, &block)
|
114
|
+
dup.rekey!(*args, &block)
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
def delete(k)
|
119
|
+
super(key_proc[k])
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
def update(other)
|
124
|
+
super(cast(other))
|
125
|
+
end
|
126
|
+
|
127
|
+
# Same as #update.
|
128
|
+
def merge!(other)
|
129
|
+
super(cast(other))
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
def replace(other)
|
134
|
+
super(cast(other))
|
135
|
+
end
|
136
|
+
|
137
|
+
#
|
138
|
+
def values_at(*keys)
|
139
|
+
super(keys.map(&key_proc))
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
def to_hash
|
144
|
+
h = {}; each{ |k,v| h[k] = v }; h
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
alias_method :to_h, :to_hash
|
149
|
+
|
150
|
+
private
|
151
|
+
|
152
|
+
#
|
153
|
+
def cast(hash)
|
154
|
+
h
|
155
|
+
hash.each do |k,v|
|
156
|
+
h[key_proc[k]] = value_proc[v]
|
157
|
+
end
|
158
|
+
h
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
#class Hash
|
165
|
+
#
|
166
|
+
# # Convert a Hash to a CastingHash.
|
167
|
+
# def to_casting_hash(value_cast=nil, &key_cast)
|
168
|
+
# CastingHash.new(self, value_cast, &key_cast)
|
169
|
+
# end
|
170
|
+
#
|
171
|
+
#end
|
@@ -0,0 +1,430 @@
|
|
1
|
+
# = Dictionary.rb
|
2
|
+
#
|
3
|
+
# Copyright (c) 2005, 2009 Jan Molic, Thomas Sawyer
|
4
|
+
#
|
5
|
+
# Ruby License
|
6
|
+
#
|
7
|
+
# This module is free software. You may use, modify, and/or redistribute this
|
8
|
+
# software under the same terms as Ruby.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
11
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
12
|
+
# FOR A PARTICULAR PURPOSE.
|
13
|
+
#
|
14
|
+
# == Acknowledgments
|
15
|
+
#
|
16
|
+
# * Andrew Johnson (merge, to_a, inspect, shift and Hash[])
|
17
|
+
# * Jeff Sharpe (reverse and reverse!)
|
18
|
+
# * Thomas Leitner (has_key? and key?)
|
19
|
+
#
|
20
|
+
# Ported from OrderHash 2.0, Copyright (c) 2005 Jan Molic
|
21
|
+
|
22
|
+
# = Dictionary
|
23
|
+
#
|
24
|
+
# The Dictionary class is a Hash that preserves order.
|
25
|
+
# So it has some array-like extensions also. By defualt
|
26
|
+
# a Dictionary object preserves insertion order, but any
|
27
|
+
# order can be specified including alphabetical key order.
|
28
|
+
#
|
29
|
+
# == Usage
|
30
|
+
#
|
31
|
+
# Just require this file and use Dictionary instead of Hash.
|
32
|
+
#
|
33
|
+
# # You can do simply
|
34
|
+
# hsh = Dictionary.new
|
35
|
+
# hsh['z'] = 1
|
36
|
+
# hsh['a'] = 2
|
37
|
+
# hsh['c'] = 3
|
38
|
+
# p hsh.keys #=> ['z','a','c']
|
39
|
+
#
|
40
|
+
# # or using Dictionary[] method
|
41
|
+
# hsh = Dictionary['z', 1, 'a', 2, 'c', 3]
|
42
|
+
# p hsh.keys #=> ['z','a','c']
|
43
|
+
#
|
44
|
+
# # but this don't preserve order
|
45
|
+
# hsh = Dictionary['z'=>1, 'a'=>2, 'c'=>3]
|
46
|
+
# p hsh.keys #=> ['a','c','z']
|
47
|
+
#
|
48
|
+
# # Dictionary has useful extensions: push, pop and unshift
|
49
|
+
# p hsh.push('to_end', 15) #=> true, key added
|
50
|
+
# p hsh.push('to_end', 30) #=> false, already - nothing happen
|
51
|
+
# p hsh.unshift('to_begin', 50) #=> true, key added
|
52
|
+
# p hsh.unshift('to_begin', 60) #=> false, already - nothing happen
|
53
|
+
# p hsh.keys #=> ["to_begin", "a", "c", "z", "to_end"]
|
54
|
+
# p hsh.pop #=> ["to_end", 15], if nothing remains, return nil
|
55
|
+
# p hsh.keys #=> ["to_begin", "a", "c", "z"]
|
56
|
+
# p hsh.shift #=> ["to_begin", 30], if nothing remains, return nil
|
57
|
+
#
|
58
|
+
# == Usage Notes
|
59
|
+
#
|
60
|
+
# * You can use #order_by to set internal sort order.
|
61
|
+
# * #<< takes a two element [k,v] array and inserts.
|
62
|
+
# * Use ::auto which creates Dictionay sub-entries as needed.
|
63
|
+
# * And ::alpha which creates a new Dictionary sorted by key.
|
64
|
+
#
|
65
|
+
class Dictionary
|
66
|
+
|
67
|
+
include Enumerable
|
68
|
+
|
69
|
+
class << self
|
70
|
+
#--
|
71
|
+
# TODO is this needed? Doesn't the super class do this?
|
72
|
+
#++
|
73
|
+
|
74
|
+
def [](*args)
|
75
|
+
hsh = new
|
76
|
+
if Hash === args[0]
|
77
|
+
hsh.replace(args[0])
|
78
|
+
elsif (args.size % 2) != 0
|
79
|
+
raise ArgumentError, "odd number of elements for Hash"
|
80
|
+
else
|
81
|
+
while !args.empty?
|
82
|
+
hsh[args.shift] = args.shift
|
83
|
+
end
|
84
|
+
end
|
85
|
+
hsh
|
86
|
+
end
|
87
|
+
|
88
|
+
# Like #new but the block sets the order.
|
89
|
+
#
|
90
|
+
def new_by(*args, &blk)
|
91
|
+
new(*args).order_by(&blk)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Alternate to #new which creates a dictionary sorted by key.
|
95
|
+
#
|
96
|
+
# d = Dictionary.alpha
|
97
|
+
# d["z"] = 1
|
98
|
+
# d["y"] = 2
|
99
|
+
# d["x"] = 3
|
100
|
+
# d #=> {"x"=>3,"y"=>2,"z"=>2}
|
101
|
+
#
|
102
|
+
# This is equivalent to:
|
103
|
+
#
|
104
|
+
# Dictionary.new.order_by { |key,value| key }
|
105
|
+
|
106
|
+
def alpha(*args, &block)
|
107
|
+
new(*args, &block).order_by_key
|
108
|
+
end
|
109
|
+
|
110
|
+
# Alternate to #new which auto-creates sub-dictionaries as needed.
|
111
|
+
#
|
112
|
+
# d = Dictionary.auto
|
113
|
+
# d["a"]["b"]["c"] = "abc" #=> { "a"=>{"b"=>{"c"=>"abc"}}}
|
114
|
+
#
|
115
|
+
def auto(*args)
|
116
|
+
#AutoDictionary.new(*args)
|
117
|
+
leet = lambda { |hsh, key| hsh[key] = new(&leet) }
|
118
|
+
new(*args, &leet)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# New Dictiionary.
|
123
|
+
|
124
|
+
def initialize(*args, &blk)
|
125
|
+
@order = []
|
126
|
+
@order_by = nil
|
127
|
+
if blk
|
128
|
+
dict = self # This ensure autmatic key entry effect the
|
129
|
+
oblk = lambda{ |hsh, key| blk[dict,key] } # dictionary rather then just the interal hash.
|
130
|
+
@hash = Hash.new(*args, &oblk)
|
131
|
+
else
|
132
|
+
@hash = Hash.new(*args)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def order
|
137
|
+
reorder if @order_by
|
138
|
+
@order
|
139
|
+
end
|
140
|
+
|
141
|
+
# Keep dictionary sorted by a specific sort order.
|
142
|
+
|
143
|
+
def order_by( &block )
|
144
|
+
@order_by = block
|
145
|
+
order
|
146
|
+
self
|
147
|
+
end
|
148
|
+
|
149
|
+
# Keep dictionary sorted by key.
|
150
|
+
#
|
151
|
+
# d = Dictionary.new.order_by_key
|
152
|
+
# d["z"] = 1
|
153
|
+
# d["y"] = 2
|
154
|
+
# d["x"] = 3
|
155
|
+
# d #=> {"x"=>3,"y"=>2,"z"=>2}
|
156
|
+
#
|
157
|
+
# This is equivalent to:
|
158
|
+
#
|
159
|
+
# Dictionary.new.order_by { |key,value| key }
|
160
|
+
#
|
161
|
+
# The initializer Dictionary#alpha also provides this.
|
162
|
+
|
163
|
+
def order_by_key
|
164
|
+
@order_by = lambda { |k,v| k }
|
165
|
+
order
|
166
|
+
self
|
167
|
+
end
|
168
|
+
|
169
|
+
# Keep dictionary sorted by value.
|
170
|
+
#
|
171
|
+
# d = Dictionary.new.order_by_value
|
172
|
+
# d["z"] = 1
|
173
|
+
# d["y"] = 2
|
174
|
+
# d["x"] = 3
|
175
|
+
# d #=> {"x"=>3,"y"=>2,"z"=>2}
|
176
|
+
#
|
177
|
+
# This is equivalent to:
|
178
|
+
#
|
179
|
+
# Dictionary.new.order_by { |key,value| value }
|
180
|
+
|
181
|
+
def order_by_value
|
182
|
+
@order_by = lambda { |k,v| v }
|
183
|
+
order
|
184
|
+
self
|
185
|
+
end
|
186
|
+
|
187
|
+
#
|
188
|
+
def reorder
|
189
|
+
if @order_by
|
190
|
+
assoc = @order.collect{ |k| [k,@hash[k]] }.sort_by(&@order_by)
|
191
|
+
@order = assoc.collect{ |k,v| k }
|
192
|
+
end
|
193
|
+
@order
|
194
|
+
end
|
195
|
+
|
196
|
+
#def ==( hsh2 )
|
197
|
+
# return false if @order != hsh2.order
|
198
|
+
# super hsh2
|
199
|
+
#end
|
200
|
+
|
201
|
+
def ==(hsh2)
|
202
|
+
if hsh2.is_a?( Dictionary )
|
203
|
+
@order == hsh2.order &&
|
204
|
+
@hash == hsh2.instance_variable_get("@hash")
|
205
|
+
else
|
206
|
+
false
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def [] k
|
211
|
+
@hash[ k ]
|
212
|
+
end
|
213
|
+
|
214
|
+
def fetch(k, *a, &b)
|
215
|
+
@hash.fetch(k, *a, &b)
|
216
|
+
end
|
217
|
+
|
218
|
+
# Store operator.
|
219
|
+
#
|
220
|
+
# h[key] = value
|
221
|
+
#
|
222
|
+
# Or with additional index.
|
223
|
+
#
|
224
|
+
# h[key,index] = value
|
225
|
+
|
226
|
+
def []=(k, i=nil, v=nil)
|
227
|
+
if v
|
228
|
+
insert(i,k,v)
|
229
|
+
else
|
230
|
+
store(k,i)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def insert( i,k,v )
|
235
|
+
@order.insert( i,k )
|
236
|
+
@hash.store( k,v )
|
237
|
+
end
|
238
|
+
|
239
|
+
def store( a,b )
|
240
|
+
@order.push( a ) unless @hash.has_key?( a )
|
241
|
+
@hash.store( a,b )
|
242
|
+
end
|
243
|
+
|
244
|
+
def clear
|
245
|
+
@order = []
|
246
|
+
@hash.clear
|
247
|
+
end
|
248
|
+
|
249
|
+
def delete( key )
|
250
|
+
@order.delete( key )
|
251
|
+
@hash.delete( key )
|
252
|
+
end
|
253
|
+
|
254
|
+
def each_key
|
255
|
+
order.each { |k| yield( k ) }
|
256
|
+
self
|
257
|
+
end
|
258
|
+
|
259
|
+
def each_value
|
260
|
+
order.each { |k| yield( @hash[k] ) }
|
261
|
+
self
|
262
|
+
end
|
263
|
+
|
264
|
+
def each
|
265
|
+
order.each { |k| yield( k,@hash[k] ) }
|
266
|
+
self
|
267
|
+
end
|
268
|
+
alias each_pair each
|
269
|
+
|
270
|
+
def delete_if
|
271
|
+
order.clone.each { |k| delete k if yield(k,@hash[k]) }
|
272
|
+
self
|
273
|
+
end
|
274
|
+
|
275
|
+
def values
|
276
|
+
ary = []
|
277
|
+
order.each { |k| ary.push @hash[k] }
|
278
|
+
ary
|
279
|
+
end
|
280
|
+
|
281
|
+
def keys
|
282
|
+
order
|
283
|
+
end
|
284
|
+
|
285
|
+
def invert
|
286
|
+
hsh2 = self.class.new
|
287
|
+
order.each { |k| hsh2[@hash[k]] = k }
|
288
|
+
hsh2
|
289
|
+
end
|
290
|
+
|
291
|
+
def reject(&block)
|
292
|
+
self.dup.delete_if(&block)
|
293
|
+
end
|
294
|
+
|
295
|
+
def reject!( &block )
|
296
|
+
hsh2 = reject(&block)
|
297
|
+
self == hsh2 ? nil : hsh2
|
298
|
+
end
|
299
|
+
|
300
|
+
def replace(hsh2)
|
301
|
+
case hsh2
|
302
|
+
when Hash
|
303
|
+
@order = hsh2.keys
|
304
|
+
@hash = hsh2
|
305
|
+
else
|
306
|
+
@order = hsh2.order
|
307
|
+
@hash = hsh2.hash
|
308
|
+
end
|
309
|
+
reorder
|
310
|
+
end
|
311
|
+
|
312
|
+
def shift
|
313
|
+
key = order.first
|
314
|
+
key ? [key,delete(key)] : super
|
315
|
+
end
|
316
|
+
|
317
|
+
def unshift( k,v )
|
318
|
+
unless @hash.include?( k )
|
319
|
+
@order.unshift( k )
|
320
|
+
@hash.store( k,v )
|
321
|
+
true
|
322
|
+
else
|
323
|
+
false
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
def <<(kv)
|
328
|
+
push(*kv)
|
329
|
+
end
|
330
|
+
|
331
|
+
def push( k,v )
|
332
|
+
unless @hash.include?( k )
|
333
|
+
@order.push( k )
|
334
|
+
@hash.store( k,v )
|
335
|
+
true
|
336
|
+
else
|
337
|
+
false
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
def pop
|
342
|
+
key = order.last
|
343
|
+
key ? [key,delete(key)] : nil
|
344
|
+
end
|
345
|
+
|
346
|
+
def inspect
|
347
|
+
ary = []
|
348
|
+
each {|k,v| ary << k.inspect + "=>" + v.inspect}
|
349
|
+
'{' + ary.join(", ") + '}'
|
350
|
+
end
|
351
|
+
|
352
|
+
def dup
|
353
|
+
a = []
|
354
|
+
each{ |k,v| a << k; a << v }
|
355
|
+
self.class[*a]
|
356
|
+
end
|
357
|
+
|
358
|
+
def update( hsh2 )
|
359
|
+
hsh2.each { |k,v| self[k] = v }
|
360
|
+
reorder
|
361
|
+
self
|
362
|
+
end
|
363
|
+
alias :merge! update
|
364
|
+
|
365
|
+
def merge( hsh2 )
|
366
|
+
self.dup.update(hsh2)
|
367
|
+
end
|
368
|
+
|
369
|
+
def select
|
370
|
+
ary = []
|
371
|
+
each { |k,v| ary << [k,v] if yield k,v }
|
372
|
+
ary
|
373
|
+
end
|
374
|
+
|
375
|
+
def reverse!
|
376
|
+
@order.reverse!
|
377
|
+
self
|
378
|
+
end
|
379
|
+
|
380
|
+
def reverse
|
381
|
+
dup.reverse!
|
382
|
+
end
|
383
|
+
|
384
|
+
#
|
385
|
+
def first(x=nil)
|
386
|
+
return @hash[order.first] unless x
|
387
|
+
order.first(x).collect { |k| @hash[k] }
|
388
|
+
end
|
389
|
+
|
390
|
+
#
|
391
|
+
def last(x=nil)
|
392
|
+
return @hash[order.last] unless x
|
393
|
+
order.last(x).collect { |k| @hash[k] }
|
394
|
+
end
|
395
|
+
|
396
|
+
def length
|
397
|
+
@order.length
|
398
|
+
end
|
399
|
+
alias :size :length
|
400
|
+
|
401
|
+
def empty?
|
402
|
+
@hash.empty?
|
403
|
+
end
|
404
|
+
|
405
|
+
def has_key?(key)
|
406
|
+
@hash.has_key?(key)
|
407
|
+
end
|
408
|
+
|
409
|
+
def key?(key)
|
410
|
+
@hash.key?(key)
|
411
|
+
end
|
412
|
+
|
413
|
+
def to_a
|
414
|
+
ary = []
|
415
|
+
each { |k,v| ary << [k,v] }
|
416
|
+
ary
|
417
|
+
end
|
418
|
+
|
419
|
+
def to_s
|
420
|
+
self.to_a.to_s
|
421
|
+
end
|
422
|
+
|
423
|
+
def to_hash
|
424
|
+
@hash.dup
|
425
|
+
end
|
426
|
+
|
427
|
+
def to_h
|
428
|
+
@hash.dup
|
429
|
+
end
|
430
|
+
end
|