class Lycopodium

Constants

VERSION

Attributes

function[RW]

Public Class Methods

new(set, function = lambda{|value| value}) click to toggle source

@param [Array] set a set of values @param [Proc] function a method that transforms a value

# File lib/lycopodium.rb, line 31
def initialize(set, function = lambda{|value| value})
  replace(set)
  @function = function
end
unique_key(data) click to toggle source
# File lib/lycopodium.rb, line 10
def self.unique_key(data)
  columns_size = data.first.size
  data.each do |row|
    unless row.size == columns_size
      raise RaggedRow, row.inspect
    end
  end

  columns = (0...columns_size).to_a
  1.upto(columns_size) do |k|
    columns.combination(k) do |combination|
      if unique_key?(data, combination)
        return combination
      end
    end
  end
  nil
end

Private Class Methods

unique_key?(data, combination) click to toggle source
# File lib/lycopodium.rb, line 76
def self.unique_key?(data, combination)
  set = Set.new
  data.each_with_index do |row,index|
    set.add(row.values_at(*combination))
    if set.size <= index
      return false
    end
  end
  true
end

Public Instance Methods

reject_collisions() click to toggle source

Removes all members of the set that collide after transformation.

@return [Array] the members of the set without collisions

# File lib/lycopodium.rb, line 39
def reject_collisions
  hashes, collisions = hashes_and_collisions

  items = []
  hashes.each do |item,hash|
    unless collisions.include?(hash)
      items << item
    end
  end
  self.class.new(items, function)
end
value_to_fingerprint() click to toggle source

Returns a mapping from the original to the transformed value.

@return [Hash] a mapping from the original to the transformed value @raise [Collision] if the method creates collisions between members of the set

# File lib/lycopodium.rb, line 55
def value_to_fingerprint
  hashes, collisions = hashes_and_collisions

  unless collisions.empty?
    message = []
    collisions.each do |collision|
      items = hashes.select do |_,hash|
        hash == collision
      end.map do |item,_|
        item
      end
      message << %(#{items.map(&:inspect) * ", "} => "#{collision}")
    end
    raise Collision, message * "\n"
  end

  hashes
end

Private Instance Methods

hashes_and_collisions() click to toggle source
# File lib/lycopodium.rb, line 87
def hashes_and_collisions
  collisions = Set.new

  hashes = {}
  counts = {}

  each do |item|
    unless hashes.key?(item)
      hashes[item] = function.call(item)
    end
    if counts.key?(hashes[item])
      collisions << hashes[item]
    else
      counts[hashes[item]] = 1
    end
  end

  [hashes, collisions]
end