Permalink
Browse files

Rework ActiveSupport::OrderedHash to make lookups faster

[#1352 state:committed]

Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
  • Loading branch information...
fcheung authored and jeremy committed Dec 9, 2008
1 parent 014b799 commit 355f41d8aafd75d76db25cdda4736e0052b0605c
@@ -171,8 +171,9 @@ def test_should_group_by_association_with_non_numeric_foreign_key
Account.expects(:columns).at_least_once.returns([column])
c = Account.count(:all, :group => :firm)
- assert_equal Firm, c.first.first.class
- assert_equal 1, c.first.last
+ first_key = c.keys.first
+ assert_equal Firm, first_key.class
+ assert_equal 1, c[first_key]
end
end
@@ -4,62 +4,49 @@ module ActiveSupport
if RUBY_VERSION >= '1.9'
OrderedHash = ::Hash
else
- class OrderedHash < Array #:nodoc:
- def []=(key, value)
- if pair = assoc(key)
- pair.pop
- pair << value
- else
- self << [key, value]
- end
- value
+ class OrderedHash < Hash #:nodoc:
+ def initialize(*args, &block)
+ super
+ @keys = []
end
- def [](key)
- pair = assoc(key)
- pair ? pair.last : nil
+ def []=(key, value)
+ if !has_key?(key)
+ @keys << key
+ end
+ super
end
def delete(key)
- pair = assoc(key)
- pair ? array_index = index(pair) : nil
- array_index ? delete_at(array_index).last : nil
+ array_index = has_key?(key) && index(key)
+ if array_index
+ @keys.delete_at(array_index)
+ end
+ super
end
def keys
- collect { |key, value| key }
+ @keys
end
def values
- collect { |key, value| value }
+ @keys.collect { |key| self[key] }
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 }
+ Hash.new(self)
end
- alias_method :value?, :has_value?
-
def each_key
- each { |key, value| yield key }
+ @keys.each { |key| yield key }
end
def each_value
- each { |key, value| yield value }
+ @keys.each { |key| yield self[key]}
+ end
+
+ def each
+ keys.each {|key| yield [key, self[key]]}
end
end
end
@@ -73,4 +73,14 @@ def test_each_value
@ordered_hash.each_value { |v| values << v }
assert_equal @values, values
end
+
+ def test_each
+ values = []
+ @ordered_hash.each {|key, value| values << value}
+ assert_equal @values, values
+ end
+
+ def test_each_with_index
+ @ordered_hash.each_with_index { |pair, index| assert_equal [@keys[index], @values[index]], pair}
+ end
end

0 comments on commit 355f41d

Please sign in to comment.