Class: Bihash

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable
Defined in:
lib/bihash.rb,
lib/bihash/version.rb,
lib/bihash/unimplemented_methods.rb

Constant Summary collapse

VERSION =
'1.2.0'
UNIMPLEMENTED_METHODS =
Set[
  # expected to only deal with half the hash: keys or values
  'keys',
  'values',
  'each_key',
  'each_value',
  'transform_keys',
  'transform_keys!',
  'transform_values',
  'transform_values!',
  # O(n) reverse lookups
  'key',
  'index',
  'rassoc',
  'value?',
  'has_value?',
  # meaningless on bihash as both sides already hashed
  'invert',
  # mass removal of nil, but a bihash can have only one pair containing nil
  'compact',
  'compact!'
]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#default_procObject

Returns the value of attribute default_proc.



97
98
99
# File 'lib/bihash.rb', line 97

def default_proc
  @default_proc
end

Class Method Details

.[](*args) ⇒ Object



9
10
11
# File 'lib/bihash.rb', line 9

def self.[](*args)
  new_from_hash(Hash[*args])
end

.try_convert(arg) ⇒ Object



13
14
15
16
# File 'lib/bihash.rb', line 13

def self.try_convert(arg)
  h = Hash.try_convert(arg)
  h && new_from_hash(h)
end

Instance Method Details

#<(rhs) ⇒ Object



18
19
20
21
# File 'lib/bihash.rb', line 18

def <(rhs)
  raise_error_unless_bihash(rhs)
  merged_hash_attrs < rhs.send(:merged_hash_attrs)
end

#<=(rhs) ⇒ Object



23
24
25
26
# File 'lib/bihash.rb', line 23

def <=(rhs)
  raise_error_unless_bihash(rhs)
  merged_hash_attrs <= rhs.send(:merged_hash_attrs)
end

#==(rhs) ⇒ Object Also known as: eql?



28
29
30
# File 'lib/bihash.rb', line 28

def ==(rhs)
  rhs.is_a?(self.class) && merged_hash_attrs == rhs.send(:merged_hash_attrs)
end

#>(rhs) ⇒ Object



32
33
34
35
# File 'lib/bihash.rb', line 32

def >(rhs)
  raise_error_unless_bihash(rhs)
  merged_hash_attrs > rhs.send(:merged_hash_attrs)
end

#>=(rhs) ⇒ Object



37
38
39
40
# File 'lib/bihash.rb', line 37

def >=(rhs)
  raise_error_unless_bihash(rhs)
  merged_hash_attrs >= rhs.send(:merged_hash_attrs)
end

#[](key) ⇒ Object



42
43
44
45
46
47
48
49
50
# File 'lib/bihash.rb', line 42

def [](key)
  if @forward.key?(key)
    @forward[key]
  elsif @reverse.key?(key)
    @reverse[key]
  else
    default_value(key)
  end
end

#[]=(key1, key2) ⇒ Object Also known as: store



52
53
54
55
56
57
58
# File 'lib/bihash.rb', line 52

def []=(key1, key2)
  raise_error_if_frozen
  delete(key1)
  delete(key2)
  @reverse[key2] = key1
  @forward[key1] = key2
end

#assoc(key) ⇒ Object



60
61
62
# File 'lib/bihash.rb', line 60

def assoc(key)
  @forward.assoc(key) || @reverse.assoc(key)
end

#clearObject



64
65
66
67
68
69
# File 'lib/bihash.rb', line 64

def clear
  raise_error_if_frozen
  @forward.clear
  @reverse.clear
  self
end

#compare_by_identityObject



71
72
73
74
75
76
# File 'lib/bihash.rb', line 71

def compare_by_identity
  raise_error_if_frozen
  @forward.compare_by_identity
  @reverse.compare_by_identity
  self
end

#default(*args) ⇒ Object



80
81
82
83
84
85
86
87
88
89
# File 'lib/bihash.rb', line 80

def default(*args)
  case args.count
  when 0
    @default
  when 1
    default_value(args[0])
  else
    raise ArgumentError, "wrong number of arguments (#{args.size} for 0..1)"
  end
end

#default=(default) ⇒ Object



91
92
93
94
95
# File 'lib/bihash.rb', line 91

def default=(default)
  raise_error_if_frozen
  @default_proc = nil
  @default = default
end

#delete(key) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/bihash.rb', line 113

def delete(key)
  raise_error_if_frozen
  if @forward.key?(key)
    @reverse.delete(@forward[key])
    @forward.delete(key)
  elsif @reverse.key?(key)
    @forward.delete(@reverse[key])
    @reverse.delete(key)
  else
    yield(key) if block_given?
  end
end

#delete_ifObject



126
127
128
129
130
131
132
133
134
# File 'lib/bihash.rb', line 126

def delete_if
  if block_given?
    raise_error_if_frozen
    @forward.each { |k,v| delete(k) if yield(k,v) }
    self
  else
    to_enum(:delete_if)
  end
end

#dig(*keys) ⇒ Object



136
137
138
# File 'lib/bihash.rb', line 136

def dig(*keys)
  (@forward.key?(keys[0]) ? @forward : @reverse).dig(*keys)
end

#each(&block) ⇒ Object Also known as: each_pair



140
141
142
143
144
145
146
147
# File 'lib/bihash.rb', line 140

def each(&block)
  if block_given?
    @forward.each(&block)
    self
  else
    to_enum(:each)
  end
end

#fetch(key, *default, &block) ⇒ Object



155
156
157
# File 'lib/bihash.rb', line 155

def fetch(key, *default, &block)
  (@forward.key?(key) ? @forward : @reverse).fetch(key, *default, &block)
end

#fetch_values(*keys) ⇒ Object



159
160
161
# File 'lib/bihash.rb', line 159

def fetch_values(*keys)
  keys.map { |key| fetch(key) }
end

#filter(&block) ⇒ Object Also known as: select



163
164
165
166
167
168
169
# File 'lib/bihash.rb', line 163

def filter(&block)
  if block_given?
    dup.tap { |d| d.select!(&block) }
  else
    to_enum(:select)
  end
end

#filter!(&block) ⇒ Object Also known as: select!



171
172
173
174
175
176
177
178
179
180
# File 'lib/bihash.rb', line 171

def filter!(&block)
  if block_given?
    raise_error_if_frozen
    old_size = size
    keep_if(&block)
    old_size == size ? nil : self
  else
    to_enum(:select!)
  end
end

#has_key?(arg) ⇒ Boolean Also known as: include?, key?, member?

Returns:

  • (Boolean)


184
185
186
# File 'lib/bihash.rb', line 184

def has_key?(arg)
  @forward.has_key?(arg) || @reverse.has_key?(arg)
end

#hashObject



188
189
190
# File 'lib/bihash.rb', line 188

def hash
  self.class.hash ^ merged_hash_attrs.hash
end

#inspectObject Also known as: to_s



194
195
196
# File 'lib/bihash.rb', line 194

def inspect
  "Bihash[#{@forward.to_s[1..-2]}]"
end

#keep_ifObject



198
199
200
201
202
203
204
205
206
# File 'lib/bihash.rb', line 198

def keep_if
  if block_given?
    raise_error_if_frozen
    @forward.each { |k,v| delete(k) unless yield(k,v) }
    self
  else
    to_enum(:keep_if)
  end
end

#merge(other_bh) ⇒ Object



214
215
216
# File 'lib/bihash.rb', line 214

def merge(other_bh)
  dup.merge!(other_bh)
end

#merge!(other_bh) ⇒ Object Also known as: update



218
219
220
221
222
223
# File 'lib/bihash.rb', line 218

def merge!(other_bh)
  raise_error_if_frozen
  raise_error_unless_bihash(other_bh)
  other_bh.each { |k,v| store(k,v) }
  self
end

#rehashObject



225
226
227
228
229
230
231
232
233
# File 'lib/bihash.rb', line 225

def rehash
  raise_error_if_frozen
  if illegal_state?
    raise 'Cannot rehash while a key is duplicated outside its own pair'
  end
  @forward.rehash
  @reverse.rehash
  self
end

#reject(&block) ⇒ Object



235
236
237
238
239
240
241
# File 'lib/bihash.rb', line 235

def reject(&block)
  if block_given?
    dup.tap { |d| d.reject!(&block) }
  else
    to_enum(:reject)
  end
end

#reject!(&block) ⇒ Object



243
244
245
246
247
248
249
250
251
252
# File 'lib/bihash.rb', line 243

def reject!(&block)
  if block_given?
    raise_error_if_frozen
    old_size = size
    delete_if(&block)
    old_size == size ? nil : self
  else
    to_enum(:reject!)
  end
end

#replace(other_bh) ⇒ Object



254
255
256
257
258
259
260
# File 'lib/bihash.rb', line 254

def replace(other_bh)
  raise_error_if_frozen
  raise_error_unless_bihash(other_bh)
  @forward.replace(other_bh.instance_variable_get(:@forward))
  @reverse.replace(other_bh.instance_variable_get(:@reverse))
  self
end

#respond_to?(method, private = false) ⇒ Boolean

Returns:

  • (Boolean)


27
28
29
# File 'lib/bihash/unimplemented_methods.rb', line 27

def respond_to?(method, private = false)
  UNIMPLEMENTED_METHODS.include?(method.to_s) ? false : super
end

#shiftObject



266
267
268
269
270
271
272
273
274
# File 'lib/bihash.rb', line 266

def shift
  raise_error_if_frozen
  if empty?
    default_value(nil)
  else
    @reverse.shift
    @forward.shift
  end
end

#slice(*args) ⇒ Object



278
279
280
281
282
283
284
# File 'lib/bihash.rb', line 278

def slice(*args)
  self.class.new.tap do |bh|
    args.each do |arg|
      bh[arg] = self[arg] if key?(arg)
    end
  end
end

#to_hObject Also known as: to_hash



288
289
290
# File 'lib/bihash.rb', line 288

def to_h
  @forward.dup
end

#to_procObject



294
295
296
# File 'lib/bihash.rb', line 294

def to_proc
  method(:[]).to_proc
end

#values_at(*keys) ⇒ Object



302
303
304
# File 'lib/bihash.rb', line 302

def values_at(*keys)
  keys.map { |key| self[key] }
end