Project

General

Profile

Feature #15143

Extend `Enumerable#to_h`

Added by sawa (Tsuyoshi Sawada) 3 months ago. Updated 3 months ago.

Status:
Closed
Priority:
Normal
Target version:
-
[ruby-core:89088]

Description

Often, we call Array#to_h to the result of Enumerable#map:

(1..5).map{|x| [x, x ** 2]}.to_h
#=> {1=>1, 2=>4, 3=>9, 4=>16, 5=>25}

I am thinking of a feature to do this in a single method call.

Currently, Enumerable#to_h does not accept a block. I propose that, when Enumerable#to_h is called with a block (that has a subarray representing a key-value pair), return a hash that would be returned by applying the block to map, and to_h to the result:

(1..5).to_h{|x| [x, x ** 2]}
#=> {1=>1, 2=>4, 3=>9, 4=>16, 5=>25}

Ideally, I request this to be done internally to Ruby without creating an intermediate parent array.


Related issues

Is duplicate of Ruby trunk - Feature #10208: Passing block to Enumerable#to_hClosed

Associated revisions

Revision abe75149
Added by nobu (Nobuyoshi Nakada) 3 months ago

Enumerable#to_h with block and so on

[Feature #15143]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64794 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 64794
Added by nobu (Nobuyoshi Nakada) 3 months ago

Enumerable#to_h with block and so on

[Feature #15143]

History

#1 [ruby-core:89089] Updated by sawa (Tsuyoshi Sawada) 3 months ago

I forgot to mention that people alternatively do:

(1..5).each_with_object({}){|x, h| h[x] = x ** 2}
#=> {1=>1, 2=>4, 3=>9, 4=>16, 5=>25}

which may be more optimal than calling map. The proposed feature also has the effect of making this technique unnecessary (although the proposal is not as effective as this in that the former creates intermediate subarrays).

#2 [ruby-core:89090] Updated by matz (Yukihiro Matsumoto) 3 months ago

  • Assignee set to nobu (Nobuyoshi Nakada)

Sounds reasonable. Accepted.

Matz.

#3 Updated by nobu (Nobuyoshi Nakada) 3 months ago

  • Is duplicate of Feature #10208: Passing block to Enumerable#to_h added

#4 [ruby-core:89091] Updated by nobu (Nobuyoshi Nakada) 3 months ago

  • Subject changed from Extend `Enumerrable#to_h` to Extend `Enumerable#to_h`

Have you changed the mind since #10208?

#5 [ruby-core:89092] Updated by mame (Yusuke Endoh) 3 months ago

If the block returns an array whose length is > 2, how does it behave?

%w(aa1 ab2 ba3 bb4).to_h {|s| s.chars }
 #=> { "a" => { "a" => "1",
                "b" => "2" },
       "b" => { "a" => "3",
                "b" => "4" } }

I expect very useful trie generator :-)

#6 [ruby-core:89097] Updated by marcandre (Marc-Andre Lafortune) 3 months ago

nobu (Nobuyoshi Nakada) wrote:

Have you changed the mind since #10208?

Or since... #666!

#7 [ruby-core:89098] Updated by sawa (Tsuyoshi Sawada) 3 months ago

Sorry that I missed the previous duplicate proposals (I found that I had even commented on one of them, which I had forgotten about). But it looks like four years have passed since then, and the situation has changed perhaps. Or, it may have worth proposing again to indicate that many people want such feature.

I am grateful to Matz for accepting this.

#8 [ruby-core:89099] Updated by sawa (Tsuyoshi Sawada) 3 months ago

mame (Yusuke Endoh) wrote:

If the block returns an array whose length is > 2, how does it behave?

%w(aa1 ab2 ba3 bb4).to_h {|s| s.chars }
 #=> { "a" => { "a" => "1",
                "b" => "2" },
       "b" => { "a" => "3",
                "b" => "4" } }

I expect very useful trie generator :-)

My original proposal is to follow the behaviour of the current map.{...}.to_h, which means to raise ArgumentError: wrong array length at 0 (expected 2, was 3).

However, mame's proposal to extend the feature also sounds interesting and good. Though, after having Matz' acceptance of this proposal, I am not sure whether we can still get another approval on top of it from him assuming mame's extension, or whether the extension should be another issue.

#9 [ruby-core:89100] Updated by matz (Yukihiro Matsumoto) 3 months ago

I changed my mind when I approved to_h.

Matz.

#10 [ruby-core:89101] Updated by matz (Yukihiro Matsumoto) 3 months ago

I don't agree with mame (Yusuke Endoh)'s idea. The return value from the block should be strictly 2 elements array.

Matz.

#11 [ruby-core:89102] Updated by sawa (Tsuyoshi Sawada) 3 months ago

Matz, thanks for confirmation. I am happy with my original proposal.

#12 [ruby-core:89107] Updated by nobu (Nobuyoshi Nakada) 3 months ago

OK, not only Enumerable, but Array, Hash, ENV, NilClass and Struct too?

#13 [ruby-core:89108] Updated by nobu (Nobuyoshi Nakada) 3 months ago

nil isn't an Enumerable, so it's irrelevant.

#14 Updated by nobu (Nobuyoshi Nakada) 3 months ago

  • Status changed from Open to Closed

Applied in changeset trunk|r64794.


Enumerable#to_h with block and so on

[Feature #15143]

#15 [ruby-core:89114] Updated by sawa (Tsuyoshi Sawada) 3 months ago

nobu (Nobuyoshi Nakada) wrote:

OK, not only Enumerable, but Array, Hash, ENV, NilClass and Struct too?

Thanks for reminding me about that and implementing it.

Also available in: Atom PDF