From 0cba4e478fb4f51f72446437b862357dc04d896f Mon Sep 17 00:00:00 2001 From: madlep Date: Wed, 24 Dec 2008 00:52:38 +1100 Subject: [PATCH] Added #each_sorted to Hash::Keys to allow the contents of a hash key/value pairs to be iterated over in as one operation by default the keys will be sorted using their natural <=> sort order, but a custom sorting lambda can be passed as an argument to do custom sorting Inspired after watching Railscasts 29 where an ugly hack had to be used to display a list of months in order and their associated tasks --- .../lib/active_support/core_ext/hash/keys.rb | 10 ++++++++++ activesupport/test/core_ext/hash_ext_test.rb | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+), 0 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/hash/keys.rb b/activesupport/lib/active_support/core_ext/hash/keys.rb index 7312bcb..3af9704 100644 --- a/activesupport/lib/active_support/core_ext/hash/keys.rb +++ b/activesupport/lib/active_support/core_ext/hash/keys.rb @@ -46,6 +46,16 @@ module ActiveSupport #:nodoc: unknown_keys = keys - [valid_keys].flatten raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty? end + + # Iterate over the key/value pairs in the hash yielding the key and value for each key after first sorting the keys. + # If no sorting_proc is provided, the natural sorting order defined by key <=> is used + def each_sorted(sorting_proc = lambda{|a,b| a <=> b}) + sorted_keys = sort &sorting_proc + sorted_keys.each do |kv| + yield kv[0], kv[1] + end + end + end end end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 63ccb5a..2e1eef8 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -22,6 +22,7 @@ class HashExtTest < Test::Unit::TestCase assert_respond_to h, :stringify_keys! assert_respond_to h, :to_options assert_respond_to h, :to_options! + assert_respond_to h, :each_sorted end def test_symbolize_keys @@ -364,6 +365,24 @@ class HashExtTest < Test::Unit::TestCase original.expects(:delete).never original.except(:a) end + + def test_each_sorted + original = {'c' => 3, 'a' => 1, 'b' => 2, 'd' => 4} + expected = [['a',1],['b',2],['c',3],['d',4]] + original.each_sorted do |key, value| + assert_equal expected.shift, [key, value] + end + end + + def test_each_sorted_custom_sorting_proc + original = {'c' => 3, 'a' => 1, 'b' => 2, 'd' => 4} + expected = [['d',4],['c',3],['b',2],['a',1]] + # sort in reverse order + original.each_sorted(lambda{|a,b| b <=> a}) do |key, value| + assert_equal expected.shift, [key,value] + end + end + end class IWriteMyOwnXML -- 1.6.0.4