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.



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/core/utils.rb', line 151

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



214
215
216
217
218
219
# File 'lib/core/utils.rb', line 214

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

#==(dh) ⇒ Object



465
466
467
468
# File 'lib/core/utils.rb', line 465

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

#add(ids, val) ⇒ Object



221
222
223
224
225
226
227
228
229
230
231
# File 'lib/core/utils.rb', line 221

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.



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/core/utils.rb', line 237

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



181
182
183
184
185
# File 'lib/core/utils.rb', line 181

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

#concat(multi_hash) ⇒ Object



291
292
293
294
295
# File 'lib/core/utils.rb', line 291

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



299
300
301
302
303
# File 'lib/core/utils.rb', line 299

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

#defaultObject



305
306
307
# File 'lib/core/utils.rb', line 305

def default
  return @values.default
end

#delete_ifObject



356
357
358
359
360
361
362
363
364
365
366
367
368
# File 'lib/core/utils.rb', line 356

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



378
379
380
381
382
383
384
# File 'lib/core/utils.rb', line 378

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

#eachObject



276
277
278
279
280
281
# File 'lib/core/utils.rb', line 276

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

#each_keyObject



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

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

#empty?Boolean

Returns:

  • (Boolean)


167
168
169
# File 'lib/core/utils.rb', line 167

def empty?
  return @keys.empty?
end

#has_key?(key) ⇒ Boolean

Returns:

  • (Boolean)


206
207
208
# File 'lib/core/utils.rb', line 206

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

#key?(key) ⇒ Boolean

Returns:

  • (Boolean)


210
211
212
# File 'lib/core/utils.rb', line 210

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

#keysObject



374
375
376
# File 'lib/core/utils.rb', line 374

def keys
  return @keys.keys
end

#rehashObject



171
172
173
174
175
# File 'lib/core/utils.rb', line 171

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

#remove(id) ⇒ Object



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/core/utils.rb', line 309

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)


177
178
179
# File 'lib/core/utils.rb', line 177

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

#valuesObject



370
371
372
# File 'lib/core/utils.rb', line 370

def values
  return @values.values
end

#values_by_id(id) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/core/utils.rb', line 187

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