class PerseusMatch::Cluster

Public Class Methods

new(phrases = [], pm_options = {}, list_options = {}) click to toggle source
Calls superclass method
# File lib/perseus_match/cluster.rb, line 35
def initialize(phrases = [], pm_options = {}, list_options = {})
  super() { |h, k| h[k] = [] }

  List.pair(phrases, pm_options, list_options) { |pm| add(pm) }
end

Public Instance Methods

<<(pm)
Alias for: add
add(pm) click to toggle source
# File lib/perseus_match/cluster.rb, line 41
def add(pm)
  self[pm.phrase] << pm
end
Also aliased as: <<
rank(options = {}) click to toggle source
# File lib/perseus_match/cluster.rb, line 89
def rank(options = {})
  coeff = options[:coeff]
  sort(options) { |match| [match.target, match.similarity(coeff)] }
end
sort(options = {}) { |*a| ... } click to toggle source
# File lib/perseus_match/cluster.rb, line 84
def sort(options = {})
  args = [:similarity, options.delete(:coeff), options]
  block_given? ? sort_by(*args) { |*a| yield(*a) } : sort_by(*args)
end
sort_by(attribute, *args) { |match| ... } click to toggle source
# File lib/perseus_match/cluster.rb, line 47
def sort_by(attribute, *args)
  options = args.last.is_a?(Hash) ? args.pop : {}

  _ = map { |phrase, matches|
    res = {}

    matches = matches.sort_by { |match|
      res[match] = match.send(attribute, *args)
    }

    # premise: if any is, then all are (i.e., only first needs checking)
    numeric = res.any? { |_, r| break r.is_a?(Numeric) }

    # sort numeric results in reverse order
    matches.reverse! if numeric

    if threshold = options[:threshold]
      condition = numeric ?
        lambda { |match| res[match] < threshold } :
        lambda { |match| res[match] > threshold }

      matches.reject!(&condition)
    end

    if limit = options[:limit]
      matches.slice!(limit..-1) if matches.size > limit
    end

    # transform entries if so requested
    matches.map! { |match| yield(match) } if block_given?

    [phrase, matches]
  }.sort

  _  # rcov hack :-(
end