Hash#rekey

T

Trans

There are a few facets (ie. extensions) I find myself using often. One
of these is Hash#rekey. I used to use other methods like those found
in the Gavin's Extensions project and DHH's ActiveSupport, eg.
#convert_keys, #symbolize_keys, #stringify_keys, and so on. But ever
since I came up with #rekey, it's been clear that it's more
advantageous and replaces all of these other methods and then some.

I think it would be a good candidate for Ruby proper -- even 1.8
series. Though it will undoubtedly be less useful in Ruby 2.0 when
string and symbol hash keys key for the same entry, it is still useful
in other ways. Here it is my implementation... note that
Symbol#to_proc is used.

require 'facets/core/symbol/to_proc'

class Hash

# Converts all keys in the Hash accroding to the given block.
# If the block return +nil+ for given key, then that key will be
# left intact.
#
# foo = { :name=>'Tom', :friend=>:Gavin }
# foo.rekey{ |k| k.to_s } #=> { "name"=>"Tom",
"friend"=>:Gavin }
# foo.inspect #=> { :name
=>"Tom", :friend=>:Gavin }

def rekey( meth=nil, &block )
raise ArgumentError, "2 for 1" if meth and block
dup.send:)rekey!, meth, &block)
end

# Synonym for Hash#rekey, but modifies the receiver in place (and
returns it).
#
# foo = { :name=>'Tom', :friend=>:Gavin }
# foo.rekey!{ |k| k.to_s } #=> { "name"=>"Tom",
"friend"=>:Gavin }
# foo.inspect #=> { "name"=>"Tom",
"friend"=>:Gavin }

def rekey!( meth=nil, &block )
meth = :to_sym unless meth or block
raise ArgumentError, "2 for 1" if meth and block
block = meth.to_sym.to_proc if meth
keys.each do |k|
nk = block[k]
self[nk]=delete(k) if nk
end
self
end

end

Improvements to implementation welcome.. no.. encouraged, of course.

T.
 
G

gwtmp01

Though it will undoubtedly be less useful in Ruby 2.0 when
string and symbol hash keys key for the same entry, it is still useful
in other ways.

I seem to remember that matz backed off from this idea.

Gary Wright
 
T

Trans

I think it would be a good candidate for Ruby proper -- even 1.8
series. Though it will undoubtedly be less useful in Ruby 2.0 when
string and symbol hash keys key for the same entry, it is still useful
in other ways. Here it is my implementation... note that
Symbol#to_proc is used.

[snip]

Sheesh I forgot the most basic examples!

{ "a"=>1, :b=>2}.rekey #=> { :a=>1, :b=>2}
{ "a"=>1, :b=>2}.rekey:)to_s) #=> { "a"=>1, "b"=>2}

T.
 
T

Trans

I seem to remember that matz backed off from this idea.

I think he backed off making Symbol a subclass of String, but I think
he's still considering auto-coercing symbol to string, or at the very
least that they will have some sort of equality for use as hash keys.
Matz?

T.
 
L

Logan Capaldo

I think he backed off making Symbol a subclass of String, but I think
he's still considering auto-coercing symbol to string, or at the very
least that they will have some sort of equality for use as hash keys.
Matz?
Incidently, I'd like to point out why I think that's an especially bad
idea (only equivalent in hashes)
["foo", :foo, 2].uniq #=> ["foo", 2]
[1, 1.0, 2].uniq #=> [1, 1.0, 2]
But; 1 == 1.0 and :foo != "foo" (at least if the equality _only_ applies
in hashes, in #hash and #eql? IOW).

I find it very "warty".
 
T

Trans

Hi,

In message "Re: Hash#rekey"

|I think he backed off making Symbol a subclass of String, but I think
|he's still considering auto-coercing symbol to string, or at the very
|least that they will have some sort of equality for use as hash keys.
|Matz?

No. "foo" and :foo are different keys in a hash.

And never the twain shall meet? So it's long live
HashWithIndifferentAccess ?

A while back I offered the idea of being able to define a key coerce
proc, eg.

h = Hash.new.key!{ |k| k.to_s }

Such that keys would always be strings. Might someting like that be a
viable solution?

In anycase, I still offer up #rekey.

T.
 
T

Trans

Hi,

In message "Re: Hash#rekey"

|> No. "foo" and :foo are different keys in a hash.
|
|And never the twain shall meet? So it's long live
|HashWithIndifferentAccess ?

The HashWithIndifferentAccess behavior will not be default even after
Ruby 2.0; that's for sure.

Okay, well I though the whole reason you considerd making Symbols a
subclass of String was basically to remove the need for this sort of
thing. Honestly, keyword lists are increasing common as prameter args
and I for get tired of putting

opts = opts.stringify_keys

at the beginning of every such method. not to mention normalizing keys
when the are stored in such hash.
|A while back I offered the idea of being able to define a key coerce
|proc, eg.
|
| h = Hash.new.key!{ |k| k.to_s }
|
|Such that keys would always be strings. Might someting like that be a
|viable solution?

Maybe, but not with a name like "key!".

|In anycase, I still offer up #rekey.

I don't think "rekey" represents the behavior well. Any better name?
transpose_keys comes to my mind.

I used 'normalize_keys' for while, but how doesn't 'rekey' fit the
behavior? The hash is being rekey'd.

T.
 
R

Ryan Davis

Incidently, I'd like to point out why I think that's an especially bad
idea (only equivalent in hashes)
["foo", :foo, 2].uniq #=> ["foo", 2]
[1, 1.0, 2].uniq #=> [1, 1.0, 2]
But; 1 == 1.0 and :foo != "foo" (at least if the equality _only_
applies
in hashes, in #hash and #eql? IOW).

Not anymore:

% ./ruby-19 -v -e 'p ["foo", :foo, 2].uniq'
ruby 1.9.0 (2007-02-05 patchlevel 0) [i686-darwin8.8.1]
["foo", :foo, 2]
 
L

Logan Capaldo

Incidently, I'd like to point out why I think that's an especially bad
idea (only equivalent in hashes)
["foo", :foo, 2].uniq #=> ["foo", 2]
[1, 1.0, 2].uniq #=> [1, 1.0, 2]
But; 1 == 1.0 and :foo != "foo" (at least if the equality _only_
applies
in hashes, in #hash and #eql? IOW).

Not anymore:

% ./ruby-19 -v -e 'p ["foo", :foo, 2].uniq'
ruby 1.9.0 (2007-02-05 patchlevel 0) [i686-darwin8.8.1]
["foo", :foo, 2]
Yeah I gathered as much from matz's replies
 
M

Martin DeMello

Hi,

In message "Re: Hash#rekey"

|I used 'normalize_keys' for while, but how doesn't 'rekey' fit the
|behavior? The hash is being rekey'd.

For me, 'rekey' is meaningless. Coined word need guessing, which is
considered harmful unless it is accepted by many.

alter_key(s), perhaps

martin
 
B

Brian Candler

alter_key(s), perhaps

# existing
a = [:eek:ne, :two, :three]
a.map! { |k| k.to_s }
puts a.inspect

# by analogy
h = [:eek:ne=>1, :two=>2, :three=>3]
h.map_keys! { |k| k.to_s }
puts h.inspect
 
T

Trans

Hi,

In message "Re: Hash#rekey"

|I used 'normalize_keys' for while, but how doesn't 'rekey' fit the
|behavior? The hash is being rekey'd.

For me, 'rekey' is meaningless. Coined word need guessing, which is
considered harmful unless it is accepted by many.

The use of re- as a prefix is very normal in English. Consider Merriam-
Webster's list

http://www.m-w.com/dictionary/re-

I certainly didn't coin the word. Common connotations include: re-
entering data via keyboard as well as altering a combination of a
lock. So, for altering the keys of a hash it makes prefect sense.

Anyway I won't go on about it any longer. Personally I'm just not
found of having to type longer winded method name.

T.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top