← Reference · Nestor G Pestelos Jr · Print this page
Programming Languages · Ruby
transform_values (Ruby Hash Method)
Reference entry · last updated September 19, 2026
Archived September 20, 2026. This version preserves earlier claims. Read the current entry.
transform_values is a method on Ruby's Hash class that returns a new Hash whose keys are unchanged and whose values are the results of applying a block to each original value.[1] It transforms the value side of a key-value map while holding the key side fixed, and it leaves the receiver untouched. Its in-place counterpart is transform_values!.
First principles and definitions
A Hash is a finite map from unique keys to values. Each key identifies at most one value, and entries iterate in the order they were created.[1] Transforming the value side alone means taking each value, producing a replacement, and rebuilding a map from the original keys and the replacement values.
transform_values is that operation. The block receives one argument, the value, and its result becomes the value at the same key. The keys are never yielded, so the block cannot change them, and the result always carries the receiver's keys.[1]
The nearest Enumerable method is map. On a Hash, map yields each entry as a two-element Array and returns an Array, so its block can change both components and can change the shape of the result. transform_values is the narrower operation: keys fixed, values replaced, and the result is still a Hash.[1]
The method is non-mutating. It returns a new Hash and leaves the receiver unchanged. The bang variant, transform_values!, performs the same replacement on the receiver itself. Ruby added both methods in version 2.4.[2]
Signature and behavior
transform_values {|value| ... } → new_hash
transform_values → new_enumerator
With a block, the method returns a new Hash. The block receives each value in turn, and the result pairs every original key with the block's output.[1]
h = {foo: 0, bar: 1, baz: 2}
h.transform_values { |value| value * 100 }
# => {:foo=>0, :bar=>100, :baz=>200}
Three properties follow from the signature.
- Keys and order are preserved. The result has the same keys as the receiver, in the same insertion order.
- The receiver is unchanged. The result is a separate Hash object, so writing to one does not affect the other.
- The default is dropped. The returned Hash has a
nildefault even when the receiver was built with a default value or a default proc. The implementation sets the new Hash's default tonil.
Without a block, the method returns a new Enumerator, which can be driven with each or combined with other Enumerable methods.[1]
h = {foo: 0, bar: 1, baz: 2}
e = h.transform_values
e.each { |value| value * 100 }
# => {:foo=>0, :bar=>100, :baz=>200}
transform_values!
transform_values! {|value| ... } → self
transform_values! → new_enumerator
The bang variant replaces each value in the receiver with the block's result and returns the receiver. It mutates the Hash in place, so any other reference to the same object observes the new values.[1] Without a block it returns an Enumerator rather than mutating.
h = {foo: 0, bar: 1, baz: 2}
h.transform_values! { |value| value * 100 }
h # => {:foo=>0, :bar=>100, :baz=>200}
Related methods
Several Hash and Enumerable methods transform entries. They differ in which component the block sees and in what the method returns.
| Method | Block sees | Result |
|---|---|---|
transform_values | Value | New Hash, keys unchanged |
transform_values! | Value | Same Hash, values replaced |
transform_keys | Key | New Hash, values unchanged |
map | Key-value pair | Array of block results |
each_value | Value | Same Hash, no replacement |
select / reject | Key-value pair | New Hash of kept or dropped entries |
transform_keys is the key-side counterpart: it rebuilds the map with new keys and the original values. When a block must change both components, or when the result should be an Array rather than a Hash, map is the method that fits.[1]
Cost
transform_values visits each entry once and builds one new Hash, so it takes linear time in the number of entries and linear additional space for the result. The values themselves are not copied; the new Hash holds whatever the block returned.
The linear cost describes the expected behavior of building a hash table from n entries. It is a conventional bound, not an asymptotic guarantee published in the Ruby documentation.
See also
References
- ^ Ruby Documentation, "Class Hash," Ruby 3.3.0. Free full text: docs.ruby-lang.org/en/3.3/Hash.html
- ^ Ruby Documentation, "Ruby 2.4.0 NEWS," Hash section, Feature #12512. Ruby 2.4.0. Free full text: docs.ruby-lang.org/en/2.4.0/NEWS.html