Hash#values
hash.values Hash#values returns a new array containing all the values from the hash, in insertion order. This method is useful when you need to extract just the values or iterate over them.
Syntax
hash.values
The syntax is short because the method itself is straightforward: take the current hash and return an array of its values. That simplicity is useful in practice, since it lets you move directly from a mapping to a sequence without having to write a lot of setup code. The examples below show a few common ways that sequence can be used.
Examples
Basic value extraction
user = { name: "Alice", email: "alice@example.com", age: 30 }
user.values
# => ["Alice", "alice@example.com", 30]
This first example shows the most direct use of Hash#values: pull out the data and leave the keys behind. It is a simple move, but it is often the right one when the next step only cares about the content. The result is still ordered, so the values stay aligned with how the hash was built.
Iteration with values
scores = { alice: 95, bob: 87, charlie: 92 }
scores.values.each do |score|
puts "Score: #{score}"
end
# Output:
# Score: 95
# Score: 87
# Score: 92
Iterating over the returned array is handy when the values are already in the right shape for display or reporting. Because values returns an array, the normal array methods are available immediately, and that can make downstream code feel very straightforward. It is a good fit when the order of the values matters more than the original keys.
Convert to a set for unique values
inventory = { apples: 5, oranges: 3, bananas: 5, grapes: 7 }
Set.new(inventory.values)
# => #<Set: {5, 3, 7}>
This pattern is useful when the values contain repeats and you only care about the distinct entries. By converting to a set after extracting the values, you can keep the extraction step separate from the uniqueness step. That makes the intention easier to read than trying to force both ideas into one expression.
Common Patterns
Check if a value exists
data = { name: "Bob", status: "active" }
data.values.include?("active")
# => true
data.values.include?("pending")
# => false
However, using Hash#value? or Hash#has_value? is more efficient for this purpose.
That efficiency note matters most when the hash is large or the check runs often. values.include? builds a full array first, while the dedicated lookup methods can answer the question without that extra work. If all you want is a membership test, the direct method is usually the better choice.
Transform values
prices = { coffee: 5, tea: 3, milk: 2 }
prices.values.map { |p| p * 1.1 }
# => [5.5, 3.3, 2.2]
Once the values are in an array, all the normal transformation tools apply. Mapping is a natural next step when the values need a quick change before being displayed or stored again. This is one of the reasons Hash#values fits well in reporting code and simple data pipelines.
Sum numeric values
cart = { apples: 3, bananas: 5, oranges: 2 }
cart.values.sum
# => 10
Summing works nicely when the hash is acting like a named bucket of counts or amounts. Extracting the values first can make the intent a little clearer than folding through key-value pairs if the keys do not matter for the calculation. The result is a compact expression that still reads like a full sentence.
Get values in sorted order (when comparable)
temps = { monday: 72, tuesday: 68, wednesday: 75 }
temps.values.sort
# => [68, 72, 75]
Sorting the values is another place where the method’s return type helps. Because values already gives you an array, the array sorting API is available immediately. That works best when the values are comparable and the key names are not part of the ordering rule.
Extract both keys and values separately
h = { a: 1, b: 2, c: 3 }
keys = h.keys
values = h.values
keys.zip(values)
# => [[:a, 1], [:b, 2], [:c, 3]]
The split-and-zip pattern is handy when you need both views of the hash in another structure. It keeps the key list and value list in step with one another, which can be useful for table rendering or for feeding another API that expects paired data. The temporary arrays are easy to read and easy to test.
Edge Cases
Empty hash
{}.values
# => []
An empty hash simply returns an empty array, which makes the method easy to use in loops and chained expressions. There is no special sentinel value to handle, so code that expects an array can keep going without extra branching. That consistency is part of why the method feels predictable.
Mixed value types
{ name: "Alice", age: 25, active: true }.values
# => ["Alice", 25, true]
Mixed types are common in Ruby hashes, especially when the hash represents a record instead of a list of uniform items. values does not try to normalize those values, so the array preserves the original mix. That can be useful when the caller wants the raw data exactly as it was stored.
Duplicate values
{ a: 1, b: 2, c: 1 }.values
# => [1, 2, 1]
Duplicates remain in the result because values is a straight extraction method, not a uniqueness filter. That behavior is often what you want when the repeated value itself carries meaning. If uniqueness matters, the caller can apply uniq or convert to a set afterward.
Values with nil
{ a: nil, b: 2, c: nil }.values
# => [nil, 2, nil]
Nil values are preserved too, which is helpful when the hash uses nil to mean “missing” or “not set.” The method does not collapse those entries away, so the shape of the data stays intact. That makes it safer for code that needs to distinguish between an absent key and an explicit nil.
Performance Considerations
Hash#values creates a new array each time it’s called. For very large hashes, this can be memory-intensive. If you only need to iterate over values, consider using Hash#each_value instead:
# Memory efficient iteration
large_hash.each_value { |value| process(value) }
When the hash is large, avoiding the extra array can matter more than the convenience of values. each_value lets you process entries one at a time, which keeps memory use lower and avoids a second pass over the same data. It is a better fit for streaming-style logic and tight loops.
Practical Considerations
Hash#values is most useful when you really need a materialized list. That works well for display code, sorting, and transformations that need random access. In a hot path, though, each_value is often a better fit because it avoids creating a second array.
The returned array preserves insertion order, which can be helpful when the hash represents form fields, configuration data, or other ordered input. Treating the result as a sequence rather than a map can make the surrounding code easier to follow.
See Also
- Hash#keys — Returns all keys
- Hash#value? — Checks if a value exists
- Hash#has_value? — Alias for value?