Project

General

Profile

Feature #13583

Adding `Hash#transform_keys` method

Added by graywolf (Gray Wolf) 6 months ago. Updated 4 months ago.

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

Description

In 2.4, new useful method Hash#transform_values was added. I would like to propose also adding matching method Hash#transform_keys.

{a: 1, b: 2}.transform_keys { |k| k.to_s }
=> {"a"=>1, "b"=>2}

What needs to be considered is what to do in case of two keys mapping to the same new key

{ a: 1, b: 2 }.transform_keys {|_| :same_key } # what should happen?

I think using Hash[] as model behaviour is a good idea.

Hash[{ a: 1, b: 2 }.map { |key, value| [:s, value] }]
=> {:s=>2}

it's also how Hash#transform_keys works in rails (afaict).

This is a follow up feature request to #9970, which seems to be stalled. If the behaviour can be agreed upon, I can try putting together a patch (if no one else wants to step up).

Associated revisions

Revision 59328
Added by mrkn (Kenta Murata) 4 months ago

hash.c: Add Hash#transform_keys and Hash#transform_keys!

  • hash.c (transform_keys_i, rb_hash_transform_keys): Add Hash#transform_keys.
    [Feature #13583]

  • hash.c (rb_hash_transform_keys_bang): Add Hash#transform_keys!.
    [Feature #13583]

  • test/ruby/test_hash.rb: Add tests for above changes.

Revision 59369
Added by kazu 4 months ago

NEWS: Add Hash#transform_keys and Hash#transform_keys!

[Feature #13583] [ci skip]

History

#1 Updated by graywolf (Gray Wolf) 6 months ago

  • Description updated (diff)

#2 Updated by graywolf (Gray Wolf) 6 months ago

  • Description updated (diff)

#3 [ruby-core:81298] Updated by shyouhei (Shyouhei Urabe) 6 months ago

Thank you for issuing this. I see there is an obvious needs for this transformation (stringify_keys) so I'm :+1: to the feature.

Let's have a concrete definition of this requested method:

  • Its name is Hash#transform_keys.
  • It returns a newly created Hash instance.
  • It has zero arity.
  • It yields,
    • with only one block parameter (which is a key of the original hash),
    • the evaluated value is the new key for the entry.
  • When the new key conflicts, later entry silently discards former entry (see the description of this issue).

Is it okey? Am I missing something? Do people have any opinion?

#4 [ruby-core:81304] Updated by graywolf (Gray Wolf) 6 months ago

I don't think you missed anything, except I would just point out to also add Hash#transform_keys!. I don't know if it's worth mentioning or just kinda automatically assumed.

#5 [ruby-core:81314] Updated by shevegen (Robert A. Heiler) 6 months ago

I think the names are good, both #transform_keys and #transform_values.

Seem quite clear to me from the names.

On the linked older issue (-3 years), the names were different,
Hash#map_keys and Hash#map_values. Matz said that the names may
be confusing. Perhaps #transform_keys and #transform_values
are better names. (I have not checked if the proposal is the
very same; shyouhei provided a very specific definition here,
including behaviour such as arity and yield-situations, which
I think the other proposal did not have). Guess matz will have
a look.

graywolf, could you perhaps show some example documentation for
the two methods?

#6 [ruby-core:82044] Updated by matz (Yukihiro Matsumoto) 4 months ago

Looks good to me.

Matz.

#7 Updated by mrkn (Kenta Murata) 4 months ago

  • Status changed from Open to Closed

Applied in changeset trunk|r59328.


hash.c: Add Hash#transform_keys and Hash#transform_keys!

  • hash.c (transform_keys_i, rb_hash_transform_keys): Add Hash#transform_keys.
    [Feature #13583]

  • hash.c (rb_hash_transform_keys_bang): Add Hash#transform_keys!.
    [Feature #13583]

  • test/ruby/test_hash.rb: Add tests for above changes.

Also available in: Atom PDF