diff --git a/activesupport/lib/active_support/core_ext/array/grouping.rb b/activesupport/lib/active_support/core_ext/array/grouping.rb index f782f8f..97980ff 100644 --- a/activesupport/lib/active_support/core_ext/array/grouping.rb +++ b/activesupport/lib/active_support/core_ext/array/grouping.rb @@ -100,6 +100,44 @@ module ActiveSupport #:nodoc: results end end + + # Same as Array#uniq but accepts block argument which result will + # be used for determining which values are unique. + # + # a = ['a', 'A', 'bb', 'bB', 'Bb', 'Cc', 'cc'] + # a.uniq { |i| i.downcase } # => ["a", "bb", "Cc"] + def uniq_with_block(&block) + if block + first_values = {} + map do |value| + key = yield value + first_values[key] ||= value + first_values[key] + end.uniq + else + uniq_without_block + end + end + + # Adds block support to Array#uniq! + def uniq_with_block!(&block) + if block + replace uniq_with_block(&block) + else + uniq_without_block! + end + end + + # This is evil and it's only because of my lack of knowledge I guess. + def self.append_features(mod) + super(mod) + mod.instance_eval do + alias_method :uniq_without_block, :uniq + alias_method :uniq, :uniq_with_block + alias_method :uniq_without_block!, :uniq! + alias_method :uniq!, :uniq_with_block! + end + end end end end diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb index 93f4482..9e6f271 100644 --- a/activesupport/test/core_ext/array_ext_test.rb +++ b/activesupport/test/core_ext/array_ext_test.rb @@ -176,6 +176,33 @@ class ArrayExtGroupingTests < Test::Unit::TestCase assert_equal [[1, 2, 3], [4, 5], [6, 7]], (1..7).to_a.in_groups(3, false) end + + def test_uniq_with_downcase + assert_equal %w{aa Bb cc}, + %w{aa aA Aa Bb bb bB cc Cc}.uniq { |e| e.downcase } + end + + def test_uniq_with_lame_block + a = %w{a b c d aa a b c d bb} + assert_equal a.uniq, a.uniq { |e| e } + end + + def test_uniq_with_empty_array + assert_equal [], [].uniq { |e| e } + end + + def test_uniq_destructive + source = %w{aa Aa bb} + source.uniq! { |e| e.downcase } + assert_equal %w{aa bb}, source + end + + def test_uniq_destructive_without_block + source = %w{aa Aa bb aa bb} + source2 = + source.uniq! + assert_equal %w{aa Aa bb}, source + end end class ArraySplitTests < Test::Unit::TestCase