Hash#count
Synopsis
hash.count # => Integer
hash.count { |key, value| block } # => Integer
Description
Hash#count returns the number of key-value pairs contained in the hash.
This method is inherited from Enumerable. See Enumerable#count for the upstream documentation.
Without a block, count returns the total number of entries, equivalent to calling length or size.
With a block, count iterates over each key-value pair and increments a counter each time the block returns a truthy value. The block receives each entry as a [key, value] two-element array, which Ruby then splats into the block’s parameters if the block has two arguments.
h = { a: 1, b: 2, c: 3 }
h.count
# => 3
h.count { |k, v| v > 1 }
# => 2
count only counts explicit entries in the hash. It does not count default values created via a default proc or lazy default values.
h = {}
h.default_proc = ->(hash, key) { hash[key] = [] }
h[:a]
h[:b]
h.count
# => 2
# The default proc created entries for :a and :b when accessed,
# so count includes them.
Arguments
Hash#count takes no arguments. If a block is given, it is passed each entry’s key and value as two separate parameters (via splatting of the internal [key, value] array).
Unlike Array#count, Hash#count does not accept an object argument — only a block is supported.
h = { name: "Alice", age: 30 }
h.count { |key, value| key.is_a?(Symbol) }
# => 2
h.count { |key, value| value.is_a?(String) }
# => 1
Return Value
Always returns an Integer. Returns 0 for an empty hash.
{}.count
# => 0
{ a: 1 }.count
# => 1
Performance
count without a block executes in constant time O(1), as it returns the hash’s internal size counter. length and size also execute in O(1).
count with a block executes in linear time O(n), where n is the number of entries, because every entry must be visited.
Gotchas and Common Mistakes
count returns an Integer; select returns a Hash. These are not interchangeable.
h = { a: 1, b: 2, c: 3 }
h.count { |k, v| v > 1 }
# => 2
h.select { |k, v| v > 1 }
# => { b: 2, c: 3 }
The block receives entries as [key, value] which Ruby splats into two parameters.
When you write |k, v|, Ruby takes the [key, value] array and unpacks it into two separate block-local variables. You cannot reassign these parameters to affect the original hash.
h = { a: 1, b: 2 }
h.count { |k, v| k == :a && v == 1 }
# => 1
# The following does NOT work as intended — the parameters
# are block-local copies, not references to hash keys:
h.count { |k, v| k = :z; v = 99; k == :a }
# => 1 (the reassignment inside the block does not change h)
Use any? for Existence Checks
If you only need to know whether at least one entry matches a condition, use any? instead of count > 0. The any? method stops iteration at the first match, while count always visits every entry.
h = { a: 1, b: 2, c: 3 }
# Visits all entries
h.count { |k, v| v > 1 } > 0
# => true
# Stops at first match
h.any? { |k, v| v > 1 }
# => true
See Also
Hash#length— returns the number of key-value pairs (alias:Hash#size)Hash#empty?— checks if the hash has no entries- Hash#select — returns a hash of matching entries
- Hash#any? — returns true if any entry matches
- Enumerable#count — upstream documentation for this method