Class: Ruleby::Core::MultiHash

Inherits:
Object
  • Object
show all
Defined in:
lib/core/utils.rb

Overview

This class is used when we need to have a Hash where keys and values are mapped many-to-many. This class allows for quick access of both key and value. It is similar to Multimap in C++ standard lib. This thing is a mess (and barely works). It needs to be refactored.

Instance Method Summary collapse

Constructor Details

#initialize(key = nil, values = []) ⇒ MultiHash

Returns a new instance of MultiHash.



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/core/utils.rb', line 171

def initialize(key=nil, values=[])
  @i = 0
  clear
  if key
    @keys = {key => []} 
    values.each do |v|
      xref = generate_xref()
      xref_list = @keys[key]
      xref_list.push xref
      @keys[key] = xref_list
      @values = {xref => v}
      @backward_hash = {xref => [key]}
    end
  end
end

Instance Method Details

#+(dh) ⇒ Object



234
235
236
237
238
239
# File 'lib/core/utils.rb', line 234

def +(dh)
  # TODO this can be faster
  new_dh = dh.dup
  dh.concat self.dup
  return new_dh
end

#==(dh) ⇒ Object



485
486
487
488
# File 'lib/core/utils.rb', line 485

def ==(dh)
  # TODO need to implement this
  return super
end

#add(ids, val) ⇒ Object



241
242
243
244
245
246
247
248
249
250
251
# File 'lib/core/utils.rb', line 241

def add(ids,val)
  xref = generate_xref()      
  ids.each do |id|
    xref_list = @keys[id]
    xref_list = [] if xref_list == @keys.default
    xref_list.push xref             
    @keys[id] = xref_list  
  end       
  @values[xref] = val    
  @backward_hash[xref] = ids
end

#add_uniq(ids, val) ⇒ Object

DEPRECATED WARN this method adds a value to the MultiHash only if it is unique. It can be a fairly costly operation, and should be avoided. We only implemented this as part of a hack to get things working early on.



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/core/utils.rb', line 257

def add_uniq(ids,val)
  xref = generate_xref()
  exist_list = []
  ids.each do |id|
    xref_list = @keys[id]
    if xref_list != @keys.default           
      xref_list.each do |existing_xref|  
        existing_val = @values[existing_xref] 
        if existing_val 
          if val == existing_val                        
            xref = existing_xref 
            exist_list.push id
            break
          end
        else
          # HACK there shouldn't be any xrefs like this in the
          # hash to being with.  Why are they there?
          xref_list.delete(existing_xref)
          @keys[id] = xref_list
        end
      end         
    end             
  end   
  add_list = ids - exist_list   
  add_list.each do |id|
    xref_list = @keys[id]
    xref_list = [] if xref_list == @keys.default
    xref_list.push xref             
    @keys[id] = xref_list  
  end            
  @values[xref] = val if exist_list.empty?
  b_list = @backward_hash[xref]
  if b_list
    @backward_hash[xref] = b_list | ids
  else
    @backward_hash[xref] = ids
  end
end

#clearObject



201
202
203
204
205
# File 'lib/core/utils.rb', line 201

def clear
  @keys = {}
  @values = {}
  @backward_hash = {}
end

#concat(multi_hash) ⇒ Object



311
312
313
314
315
# File 'lib/core/utils.rb', line 311

def concat(multi_hash)
  multi_hash.each do |ids,val|
    add(ids,val)
  end
end

#concat_uniq(double_hash) ⇒ Object

DEPRECATED WARN see comments in add_uniq



319
320
321
322
323
# File 'lib/core/utils.rb', line 319

def concat_uniq(double_hash)
  double_hash.each do |ids,val|
    add_uniq(ids,val)
  end
end

#defaultObject



325
326
327
# File 'lib/core/utils.rb', line 325

def default
  return @values.default
end

#delete_ifObject



376
377
378
379
380
381
382
383
384
385
386
387
388
# File 'lib/core/utils.rb', line 376

def delete_if
  @values.delete_if do |xref,v|  
    if yield(v)
      id_list = @backward_hash.delete(xref)
      id_list.each do |next_id|
        remove_internal(next_id,xref)
      end
      true
    else
      false
    end
  end
end

#dupObject



398
399
400
401
402
403
404
# File 'lib/core/utils.rb', line 398

def dup
  dup_mc = MultiHash.new
  each do |ids,v|
    dup_mc.add ids, v.dup
  end
  return dup_mc      
end

#eachObject



296
297
298
299
300
301
# File 'lib/core/utils.rb', line 296

def each
  @values.each do |xref,val|
    ids = @backward_hash[xref]        
    yield(ids,val)
  end
end

#each_keyObject



220
221
222
223
224
# File 'lib/core/utils.rb', line 220

def each_key
  @keys.each_key do |key|
    yield(key)
  end
end

#empty?Boolean

Returns:

  • (Boolean)


187
188
189
# File 'lib/core/utils.rb', line 187

def empty?
  return @keys.empty?
end

#has_key?(key) ⇒ Boolean

Returns:

  • (Boolean)


226
227
228
# File 'lib/core/utils.rb', line 226

def has_key?(key)
  return @keys.has_key?(key)
end

#key?(key) ⇒ Boolean

Returns:

  • (Boolean)


230
231
232
# File 'lib/core/utils.rb', line 230

def key?(key)
  return has_key?(key)
end

#keysObject



394
395
396
# File 'lib/core/utils.rb', line 394

def keys
  return @keys.keys
end

#rehashObject



191
192
193
194
195
# File 'lib/core/utils.rb', line 191

def rehash
  @keys.rehash
  @values.rehash
  @backward_hash.rehash
end

#remove(id) ⇒ Object



329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/core/utils.rb', line 329

def remove(id)      
  xref_list = @keys.delete(id)
  if xref_list != @keys.default
    removed_values = []
    xref_list.each do |xref|
      value = @values.delete(xref)
      removed_values.push value
      id_list = @backward_hash.delete(xref)
      id_list.each do |next_id|
        remove_internal(next_id,xref) if next_id != id
      end
    end
    return removed_values
  else
  #        puts 'WARN: tried to remove from MultiHash where id does not exist'        
    return default
  end
end

#value?(mr) ⇒ Boolean

Returns:

  • (Boolean)


197
198
199
# File 'lib/core/utils.rb', line 197

def value?(mr)
  @values.value?(mr)
end

#valuesObject



390
391
392
# File 'lib/core/utils.rb', line 390

def values
  return @values.values
end

#values_by_id(id) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/core/utils.rb', line 207

def values_by_id(id)
  xrefs = @keys[id]
  values = []
  if xrefs
    xrefs.each do |k|
      values.push @values[k]
    end
  else
    #???
  end
  return values
end