class Hash
  # For a hash whose keys are strings of Class names, this will delete any pairs that have
  # nonexistant class names.
  def validate_value_klass(klass)
    self.each {|sid,obj|
      if obj.class != Object.const_get(klass)
        warn "object of '#{sid}' not a #{klass}"
        self.delete(sid)
      end
    }
  end  

  # Returns a hash which will set its values by calling each value with the given method and optional argument.
  # If a block is passed, each value will be set the value returned by its block call.
  def vmap(arg=nil,method='[]',&block)
    new = {}
    if block
      self.each {|k,v|
        v1 = yield(k,v)
        new[k] = v1
      }
    else  
      self.each {|k,v|
        new[k] = arg.nil? ? v.send(method) : v.send(method,arg)
      }
    end
    new
  end
  
  # Same as vmap() but merges its results with the existing hash.
  def vmap!(*args,&block)
    self.update(vmap(*args,&block))
  end

  # For a hash whose values are arrays, this will return a hash with each value substituted by the
  # size of the value.
  def vsize
    vmap(nil,'size')
  end

  # Same as pass_keys!() but replaces the hash with the resulting hash.
  def only_keep(arr=[],opt={})
    delete_keys!(self.keys - arr,opt)
  end

  def delete_keys!(arr=[],opt={}) #:nodoc:
    deleted = {}
    arr.each {|e| 
      puts "deleting #{e}" if opt[:verbose]
      deleted[e] = self.delete(e) if has_key?(e)
    }
    deleted
  end
  
  # Returns a subset of the hash for the specified keys. These entries will be deleted from the
  # original hash.
  def pass_keys!(*keys)
    delete_keys!(keys)
  end

  # For a hash whose values are arrays, this will set each unique element in a value array as a key
  # and set its values to all the keys it occurred in.
  # This is useful when modeling one to many relationships with keys
  # and values.
  def transform_many
    b = {}
    each {|k,arr| 
      #raise "#{arr.inspect} not an Array" if arr.class != Array
      arr = [arr] if arr.class != Array
      arr.each {|e| 
        b.has_key?(e) ? b[e].push(k) : b[e] = [k]
      }
    }
    b
  end

  #Sorts hash by values, returning them as an array of array pairs.
  def vsort
    sort { |a,b| b[1]<=>a[1] }
  end
end