Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions activesupport/lib/active_support/core_ext/enumerable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,36 @@ def group_by
assoc
end unless [].respond_to?(:group_by)

# Return the counts of the objects in the enumerable matching the result of
# the block. Useful, for example, for counting the parents by their number of
# children or counting users by their status.
#
# Examples:
#
# parents.count_by do |parent|
# parent.children.count
# end
# "1 -> 12"
# "2 -> 8"
# "3 -> 10"
# "7 -> 1"
#
# users.count_by(&:status)
# "active -> 37"
# "inactive -> 4"
# "blacklisted -> 2"
# "pending -> 17"
def count_by(&block)
counts = {}

grouped = group_by(&block)
grouped.each do |key, vals|
counts[key] = vals.size
end

counts
end

# Calculates a sum from the elements. Examples:
#
# payments.sum { |p| p.price * p.tax_rate }
Expand Down
20 changes: 20 additions & 0 deletions activesupport/test/core_ext/enumerable_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@ def test_group_by
assert({}.merge(grouped), "Could not convert ActiveSupport::OrderedHash into Hash")
end

def test_count_by
names = %w(alexander andy bob jacob janet joe mel peter susan)

length_counts = names.count_by(&:length)

assert_equal [3, 4, 5, 9], length_counts.keys.sort
assert_equal length_counts[3], 3
assert_equal length_counts[4], 1
assert_equal length_counts[5], 4
assert_equal length_counts[9], 1

letter_counts = names.count_by { |name| name.first }
assert_equal %w(a b j m p s), letter_counts.keys.sort
assert_equal letter_counts["a"], 2
assert_equal letter_counts["b"], 1
assert_equal letter_counts["j"], 3
assert_equal letter_counts["m"], 1
assert_equal letter_counts["s"], 1
end

def test_sums
assert_equal 30, [5, 15, 10].sum
assert_equal 30, [5, 15, 10].sum { |i| i }
Expand Down