Project

General

Profile

Actions

Feature #20769

open

Add `Hash#transform_value`

Added by seanpdoyle (Sean Doyle) 2 days ago. Updated 1 day ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:119332]

Description

Add Hash#transform_value as a specialized, key-specific version of Hash#transform_values.

hash = { image: "https://example.com/image.jpg" }
mutated_hash = hash.transform_value(:image) { |url| download(url) }

hash # => { image: "https://example.com/image.jpg" }
mutated_hash # => { image: File<...> }

hash.transform_value!(:image) { |url| download(url) }
hash # => { image: File<...> }

Similar value transformation can be achieved through variable assignment and direct mutation:

hash = { image: "https://example.com/image.jpg" }

hash.merge(image: download(hash[:image]))

hash[:image] = download(hash[:image])

While simple and currently supported, it requires a local variable (and therefore poses some challenges when chaining other methods) and repeats the Hash key in both the reading and writing portions of the code.

Updated by nobu (Nobuyoshi Nakada) 1 day ago

hash.merge(image: nil) {|_, url| download(url)}

hash.merge!(image: nil) {|_, url| download(url)}

Updated by seanpdoyle (Sean Doyle) 1 day ago

Thank you for sharing that code sample. It demonstrates an interesting way to use Hash#merge with a block argument.

When the key argument is absent from the Hash, a call to Hash#transform_value would be a no-operation. I apologize for not including this in the original example:

hash  = { foo: "value" }
transformed_hash = hash.transform_key(:bar) { |value| fail "This block is never yielded" }
transformed_hash # => { foo: "value" }

nobu (Nobuyoshi Nakada) wrote in #note-1:

hash.merge(image: nil) {|_, url| download(url)}

hash.merge!(image: nil) {|_, url| download(url)}

Using Hash#merge in the way you have shared does reduce the number times the key name is repeated.

However, without a guarding conditional call to hash.key?(:image), the returned Hash would include image: nil when an :image key was not initially present:

hash = {}
transformed_hash = hash.merge(image: nil) { |_, url| download(url) }
transformed_hash # => { image: nil }

hash = {}
transformed_hash = hash.merge(image: nil) { |_, url| download(url) } if hash.key?(:image)
transformed_hash # => {}
Actions

Also available in: Atom PDF

Like0
Like0Like0