Skip to content

Instantly share code, notes, and snippets.

@chuyeow
Created December 11, 2008 02:23
Show Gist options
  • Save chuyeow/34577 to your computer and use it in GitHub Desktop.
Save chuyeow/34577 to your computer and use it in GitHub Desktop.
# Micro-benchmark for new OrderedHash impl in http://github.com/rails/rails/commit/355f41d8aafd75d76db25cdda4736e0052b0605c
class OrderedHash < Hash
def initialize(*args, &block)
super
@keys = []
end
def []=(key, value)
if !has_key?(key)
@keys << key
end
super
end
def delete(key)
array_index = has_key?(key) && index(key)
if array_index
@keys.delete_at(array_index)
end
super
end
def keys
@keys
end
def values
@keys.collect { |key| self[key] }
end
def to_hash
Hash.new(self)
end
def each_key
@keys.each { |key| yield key }
end
def each_value
@keys.each { |key| yield self[key]}
end
def each
keys.each {|key| yield [key, self[key]]}
end
end
class OrderedHashOld < Array
def []=(key, value)
if pair = assoc(key)
pair.pop
pair << value
else
self << [key, value]
end
value
end
def [](key)
pair = assoc(key)
pair ? pair.last : nil
end
def delete(key)
pair = assoc(key)
pair ? array_index = index(pair) : nil
array_index ? delete_at(array_index).last : nil
end
def keys
collect { |key, value| key }
end
def values
collect { |key, value| value }
end
def to_hash
returning({}) do |hash|
each { |array| hash[array[0]] = array[1] }
end
end
def has_key?(k)
!assoc(k).nil?
end
alias_method :key?, :has_key?
alias_method :include?, :has_key?
alias_method :member?, :has_key?
def has_value?(v)
any? { |key, value| value == v }
end
alias_method :value?, :has_value?
def each_key
each { |key, value| yield key }
end
def each_value
each { |key, value| yield value }
end
end
module Enumerable
def old_group_by
assoc = OrderedHashOld.new
each do |element|
key = yield(element)
if assoc.has_key?(key)
assoc[key] << element
else
assoc[key] = [element]
end
end
assoc
end
def new_group_by
assoc = OrderedHash.new
each do |element|
key = yield(element)
if assoc.has_key?(key)
assoc[key] << element
else
assoc[key] = [element]
end
end
assoc
end
end
require 'benchmark'
include Benchmark
array = (1..100000).to_a
bmbm(5) do |x|
x.report('old') do
array.old_group_by {|i| i % 13}
end
x.report('new') do
array.new_group_by {|i| i % 13}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment