Skip to content
forked from hopsoft/goldmine

Enumerable#group_by on steroids with an extra dash of awesome. Think of it as MapReduce for mortals.

License

Notifications You must be signed in to change notification settings

spencerroan/pivot

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

#1on1 one-pivot GEM

##Overview The one-pivot GEM provides a simple way to mine data from a list of objects. There are no constraints on the types of objects that you can pivot. You can pivot anything from a list of numbers to a list of ActiveRecord objects to anything in between.

One::Pivoter exposes two methods of importance.

  • pivot - runs a single pivot
  • multi-pivot - stacks multiple pivots into a single result

A pivot is simply a Ruby block (or Proc) that executes for each item in the list. The result returned from this block then serves as the key in the resulting Hash.

Lets have a look at some examples.

Note: there are a few advanced features not demonstrated in the examples below. For example, adding identifiers to pivots or attaching observers to pivot operations. We use these features at 1on1 to cache pivot results for each item. This gives us a big performance boost when the same item participates in multiple pivots during its lifetime... especially when the pivot Proc is an expensive operation. Have a look at the tests when you want to dig a little deeper.

##Installation gem install one-pivot

##A simple single pivot require 'one-pivot'

# create the pivot instance
pivoter = One::Pivoter.new

# create a list of objects to pivot
list = [1,2,3,4,5,6,7,8,9]

# run a single pivot
# note: the block passed to the pivot method is invoked for each item in the list
# note: the result from the block will act as the 'key' in the resulting Hash
result = pivoter.pivot(list) {|item| item <= 5}

# 'result' will be a Hash with the following structure
{
  true => [1,2,3,4,5],
  false => [6,7,8,9]
}

##A simple multi-pivot require 'one-pivot'

# create the pivot instance
# note: the multi-pivot delimiter that was specified
pivoter = One::Pivoter.new

# create a list of objects to pivot
list = [1,2,3,4,5,6,7,8,9]

# run several pivots together
pivots = []

pivots << lambda do |i|
  key = "less than or equal to 5" if i <= 5
  key ||= "greater than 5"
end

pivots << lambda do |i|
  key = "greater than or equal to 3" if i >= 3
  key ||= "less than 3"
end

pivots << {:delimiter => " & "}

result = pivoter.multi_pivot(list, *pivots)

# 'result' will be a Hash with the following structure
{
  "less than or equal to 5 & greater than or equal to 3" => [3, 4, 5],
  "less than or equal to 5 & less than 3" => [1, 2],
  "greater than 5 & greater than or equal to 3" => [6, 7, 8, 9]
}

##A real world example # we'll be working with ActiveRecord objects based on the following schema # ============================================================================ # create_table "users", :force => true do |t| # t.string "name" # t.datetime "created_at" # t.datetime "updated_at" # end # # create_table "skills", :force => true do |t| # t.string "name" # t.datetime "created_at" # t.datetime "updated_at" # end # # create_table "skills_users", :id => false, :force => true do |t| # t.integer "user_id" # t.integer "skill_id" # end # # and will seed the datbase with the following data # ============================================================================ # ruby = Skill.create(:name => "Ruby") # python = Skill.create(:name => "Python") # php = Skill.create(:name => "PHP") # javascript = Skill.create(:name => "JavaScript") # # users = User.create([ # {:name => "Ryan", :skills => [ruby]}, # {:name => "Dave", :skills => [php, javascript]}, # {:name => "Brett", :skills => [ruby, javascript]}, # {:name => "Jay", :skills => [ruby, python, php, javascript]}, # {:name => "Doug"} # ]) #

require 'one-pivot'

pivoter = One::Pivoter.new
# note that the pivot block returns an array
# each unique value in the arrays returned will become a key in the resulting Hash
result = pivoter.pivot(User.all) do |user|
  user.skills
end

# 'result' will be Hash with the following structure
# note: I've simplified the object structure (using names only) for clarity
{
  "Ruby" => ["Brett", "Jay", "Ryan"],
  "PHP" => ["Dave", "Jay"],
  "JavaScript" => ["Brett", "Dave", "Jay"],
  "Python" => ["Jay"],
  nil => ["Doug"]
}

About

Enumerable#group_by on steroids with an extra dash of awesome. Think of it as MapReduce for mortals.

Resources

License

Stars

Watchers

Forks

Packages

No packages published