Feature #10208
closedPassing block to Enumerable#to_h
Description
Now that we can convert 'a list of [key, value] pairs' into a hash with Enumerable#to_h,
how about make it take a block to specify 'how to convert each element into a [key, value] pair'?
Example:
# Convert users into an {id => name} hash
users.map{|u| [u.id, u.name]}.to_h
↓
# Convert users into an {id => name} hash
users.to_h{|u| [u.id, u.name]}
This could also be a solution for these feature requests:
-
Feature #6669 A method like Hash#map but returns hash
hsh.apply{|k, v| [k.to_s, v]} == hsh.to_h{|k, v| [k.to_s, v]}
-
Feature #7793 New methods on Hash
Feature #9970 AddHash#map_keys
andHash#map_values
hsh.map_k(&:to_s) == hsh.to_h{|k, v| [k.to_s, v]} hsh.map_v(&:to_i) == hsh.to_h{|k, v| [k, v.to_i]} hsh.map_kv(&block) == hsh.to_h(&block)
Updated by nobu (Nobuyoshi Nakada) about 10 years ago
The name to_h
doesn't feel nice for it, IMHO.
Updated by matz (Yukihiro Matsumoto) about 10 years ago
I agree with Nobu.
Matz.
Updated by marcandre (Marc-Andre Lafortune) about 10 years ago
I agree to_h
isn't the right method to do this.
I completely agree that we need new methods to do this.
This would also be a solution for #4151, and the multiple other proposals related to it.
Updated by sawa (Tsuyoshi Sawada) about 10 years ago
I think the creation of intermediate arrays for each pair is waste of resource. Can we use combination of two methods? For example, something like:
users.with_keys(&:id).with_values(&:name)
or
users.with_values(&:name).with_keys(&:id)
Order of application of the two methods with_keys
and with_values
should not matter. When only one of them has applied, the return value should be something like an enumerator. As soon as both methods have applied, a hash should be returned.
Updated by yhara (Yutaka HARA) about 10 years ago
Marc-Andre Lafortune wrote:
I completely agree that we need new methods to do this.
Thanks. One idea is name it Enumerable#hash_by (like max_by, group_by)
User = Struct.new(:id, :name)
users = [User.new(1, "Alice"), User.new(2, "Bob")]
users.hash_by{|u| [u.id, u.name]}
# {1 => "Alice", 2 => "Bob"}
Updated by matz (Yukihiro Matsumoto) about 10 years ago
We have #max and #max_by. When we have #hash and #hash_by, people may expect something else.
But it may not matter much. Or maybe we need to rename #hash to #hashcode (off topic here).
Matz.
Updated by knu (Akinori MUSHA) over 8 years ago
I like this proposal. I think it is reasonable for to_h
to take an optional block to specify how to make a hash from a given enumerable object because most enumerable objects are not composed of two element arrays. (IIRC that was the reason why Matz didn't like the idea of adding the method when it was first proposed)
The said use case users.map{|u| [u.id, u.name]}.to_h
is only as effective as Hash[users.map{|u| [u.id, u.name]}]
, and that spoils the usefulness of the method defined in Enumerable. users.lazy.map{|u| [u.id, u.name]}.to_h
may be cool in that it does not create an intermediate array object, but it still creates a couple of chained lazy enumerable objects and looks far from being concise and straightforward.
What do you guys think? I don't think we need a new name for this.
Updated by shyouhei (Shyouhei Urabe) over 8 years ago
We looked at this issue at yesterday's developer meeting and had consensus that there is no other example of to_* method that takes a block. Introducing such new concept seems too risky.
Updated by knu (Akinori MUSHA) about 8 years ago
So, we need a different name for this.
Here's some candidates I can think of:
- hash_by (proposed above)
- to_h_by
- hash_map
- map_h
- map_to_h
Updated by shyouhei (Shyouhei Urabe) about 8 years ago
- Related to Feature #12512: Import Hash#transform_values and its destructive version from ActiveSupport added
Updated by shyouhei (Shyouhei Urabe) about 8 years ago
- Description updated (diff)
Not a direct translation of the proposed method, but Hash#transform_values is now available. https://bugs.ruby-lang.org/issues/12512
Updated by shyouhei (Shyouhei Urabe) almost 8 years ago
- Status changed from Open to Feedback
FYI if there are people who need this functionality: so far we have not found an appropriately sounding name of this method. It should be a method of Enumerable (not only Hash), that takes a block, and returns a Hash.
Updated by nobu (Nobuyoshi Nakada) about 6 years ago
- Has duplicate Feature #15143: Extend `Enumerable#to_h` added
Updated by knu (Akinori MUSHA) about 6 years ago
So, exactly the same proposal linked above got accepted. The name wasn't actually a problem!
Well, congratulations anyway! 😆
Updated by yhara (Yutaka HARA) about 6 years ago
- Status changed from Feedback to Closed