Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Transform hash key?

Reply
Thread Tools

Transform hash key?

 
 
MSG
Guest
Posts: n/a
 
      01-31-2006
I'd like to change a hash's keys from all lower cases to upper
The code below works but it just doesn't *feel* right with %temp.
Can it be done in a short one line of code, like how map() works
on arrays?

#!/usr/bin/perl

use strict;
use warnings;

my %h = ( a=>"1x", c=>"2y", b=>"3z" );
my %temp;
foreach my $k (keys %h){
$temp{uc $k} = $h{$k};
}
%h = %temp; # %h = (A=>"1x", c=>"2y", B=>"3z")

 
Reply With Quote
 
 
 
 
A. Sinan Unur
Guest
Posts: n/a
 
      01-31-2006
"MSG" <(E-Mail Removed)> wrote in news:1138685184.204561.68790
@z14g2000cwz.googlegroups.com:

> I'd like to change a hash's keys from all lower cases to upper
> The code below works but it just doesn't *feel* right with %temp.
> Can it be done in a short one line of code, like how map() works
> on arrays?
>
> #!/usr/bin/perl
>
> use strict;
> use warnings;
>
> my %h = ( a=>"1x", c=>"2y", b=>"3z" );
> my %temp;
> foreach my $k (keys %h){
> $temp{uc $k} = $h{$k};
> }
> %h = %temp; # %h = (A=>"1x", c=>"2y", B=>"3z")


#!/usr/bin/perl

use warnings;
use strict;

my %h = (a => "1x", c => "2y", b => "3z");
%h = map { uc $_ => $h{$_} } keys %h;

use Data:umper;
print Dumper \%h;

--
A. Sinan Unur <(E-Mail Removed)>
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:
http://mail.augustmail.com/~tadmc/cl...uidelines.html

 
Reply With Quote
 
 
 
 
MSG
Guest
Posts: n/a
 
      01-31-2006

A. Sinan Unur wrote:
> "MSG" <(E-Mail Removed)> wrote in news:1138685184.204561.68790
> @z14g2000cwz.googlegroups.com:
>
> > I'd like to change a hash's keys from all lower cases to upper
> > The code below works but it just doesn't *feel* right with %temp.
> > Can it be done in a short one line of code, like how map() works
> > on arrays?
> >
> > #!/usr/bin/perl
> >
> > use strict;
> > use warnings;
> >
> > my %h = ( a=>"1x", c=>"2y", b=>"3z" );
> > my %temp;
> > foreach my $k (keys %h){
> > $temp{uc $k} = $h{$k};
> > }
> > %h = %temp; # %h = (A=>"1x", c=>"2y", B=>"3z")

>
> #!/usr/bin/perl
>
> use warnings;
> use strict;
>
> my %h = (a => "1x", c => "2y", b => "3z");
> %h = map { uc $_ => $h{$_} } keys %h;
>
> use Data:umper;
> print Dumper \%h;
>
> --
> A. Sinan Unur <(E-Mail Removed)>
> (reverse each component and remove .invalid for email address)
>
> comp.lang.perl.misc guidelines on the WWW:
> http://mail.augustmail.com/~tadmc/cl...uidelines.html


Thanks! It is exactly what I am looking for!

 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      01-31-2006
"MSG" <(E-Mail Removed)> wrote in news:1138687376.623849.42190
@g47g2000cwa.googlegroups.com:

> A. Sinan Unur wrote:
>> "MSG" <(E-Mail Removed)> wrote in news:1138685184.204561.68790
>> @z14g2000cwz.googlegroups.com:
>>
>> > I'd like to change a hash's keys from all lower cases to upper

....
>> my %h = (a => "1x", c => "2y", b => "3z");
>> %h = map { uc $_ => $h{$_} } keys %h;
>>
>> use Data:umper;
>> print Dumper \%h;
>>
>> --
>> A. Sinan Unur <(E-Mail Removed)>
>> (reverse each component and remove .invalid for email address)
>>
>> comp.lang.perl.misc guidelines on the WWW:
>> http://mail.augustmail.com/~tadmc/cl...uidelines.html

>
> Thanks! It is exactly what I am looking for!


You are welcome. Glad to be of help.

However, I presume, you were not looking for my signature. Please trim
the quoted material in your replies, and don't quote signatures.

Sinan

--
A. Sinan Unur <(E-Mail Removed)>
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:
http://mail.augustmail.com/~tadmc/cl...uidelines.html

 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      01-31-2006
>>>>> "ASU" == A Sinan Unur <(E-Mail Removed)> writes:

ASU> "MSG" <(E-Mail Removed)> wrote in news:1138685184.204561.68790
ASU> @z14g2000cwz.googlegroups.com:

>> I'd like to change a hash's keys from all lower cases to upper
>> The code below works but it just doesn't *feel* right with %temp.
>> Can it be done in a short one line of code, like how map() works
>> on arrays?


ASU> my %h = (a => "1x", c => "2y", b => "3z");
ASU> %h = map { uc $_ => $h{$_} } keys %h;

i would use the for modifier (untested)

$h{uc $_} = delete $h{$_} for keys %h;

i expect it to be faster but only benchmark knows for sure!

uri

--
Uri Guttman ------ http://www.velocityreviews.com/forums/(E-Mail Removed) -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      01-31-2006
Uri Guttman <(E-Mail Removed)> wrote in news(E-Mail Removed):

>>>>>> "ASU" == A Sinan Unur <(E-Mail Removed)> writes:

>
> ASU> "MSG" <(E-Mail Removed)> wrote in news:1138685184.204561.68790
> ASU> @z14g2000cwz.googlegroups.com:
>
> >> I'd like to change a hash's keys from all lower cases to upper
> >> The code below works but it just doesn't *feel* right with %temp.
> >> Can it be done in a short one line of code, like how map() works
> >> on arrays?

>
> ASU> my %h = (a => "1x", c => "2y", b => "3z");
> ASU> %h = map { uc $_ => $h{$_} } keys %h;
>
> i would use the for modifier (untested)
>
> $h{uc $_} = delete $h{$_} for keys %h;
>
> i expect it to be faster but only benchmark knows for sure!


Hmmm ... yes, this is neat.

#!/usr/bin/perl

use warnings;
use strict;

use Benchmark qw( cmpthese );

my %h = map { $_ => 1 } ('aaa' .. 'zzz');

cmpthese -1, {
map => sub { %h = map { uc $_ => $h{$_} } keys %h },
for => sub { $h{uc $_} = delete $h{$_} for keys %h; },
};

D:\Home\asu1\UseNet\clpmisc> s.pl
Rate map for
map 12.4/s -- -60%
for 31.5/s 153% --

So the for loop takes about 1/3 of the time the map takes, and
this ratio remains roughly constant when the number of keys is
increased.

Nice.
--
A. Sinan Unur <(E-Mail Removed)>
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:
http://mail.augustmail.com/~tadmc/cl...uidelines.html
 
Reply With Quote
 
DJ Stunks
Guest
Posts: n/a
 
      01-31-2006

A. Sinan Unur wrote:
>
> #!/usr/bin/perl
>
> use warnings;
> use strict;
>
> use Benchmark qw( cmpthese );
>
> my %h = map { $_ => 1 } ('aaa' .. 'zzz');
>
> cmpthese -1, {
> map => sub { %h = map { uc $_ => $h{$_} } keys %h },
> for => sub { $h{uc $_} = delete $h{$_} for keys %h; },
> };
>
> D:\Home\asu1\UseNet\clpmisc> s.pl
> Rate map for
> map 12.4/s -- -60%
> for 31.5/s 153% --
>
> So the for loop takes about 1/3 of the time the map takes, and
> this ratio remains roughly constant when the number of keys is
> increased.
>
> Nice.


Would it be possible to alias the keys and edit in-place? It would be
easy to do so with the values, but I'm not sure about the keys.

Just wondering.

Tks.
-jp

 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      01-31-2006
>>>>> "ASU" == A Sinan Unur <(E-Mail Removed)> writes:

ASU> my %h = map { $_ => 1 } ('aaa' .. 'zzz');

ASU> cmpthese -1, {
ASU> map => sub { %h = map { uc $_ => $h{$_} } keys %h },
ASU> for => sub { $h{uc $_} = delete $h{$_} for keys %h; },
ASU> };

this benchmark has a common problem in that you don't set up the hash
the same way for each run. the first time you call either sub, the hash
will have only upper case keys. now i doubt that uc will be faster or
slower given any mix of input case but it still is wrong. if the
transform were something whose speed was data dependent, this benchmark
would be very bogus.

the map one could be fixed just by assigning it to a different hash. the
for one would need a fresh hash each time as it modifies it in place. so
you would need to do the same work for each one and my best idea would
be to copy the %h to %h2 inside each sub and use that as the input (and
you can use it for the output of the map. also choosing a different
output hash for the map could affect speed as well.

this is just a small lesson on the difficulty of properly benchmarking
apples and apples.

uri

--
Uri Guttman ------ (E-Mail Removed) -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      01-31-2006
>>>>> "DS" == DJ Stunks <(E-Mail Removed)> writes:

>>
>> my %h = map { $_ => 1 } ('aaa' .. 'zzz');
>>
>> cmpthese -1, {
>> map => sub { %h = map { uc $_ => $h{$_} } keys %h },
>> for => sub { $h{uc $_} = delete $h{$_} for keys %h; },
>> };
>>
>> D:\Home\asu1\UseNet\clpmisc> s.pl
>> Rate map for
>> map 12.4/s -- -60%
>> for 31.5/s 153% --


>> Nice.


DS> Would it be possible to alias the keys and edit in-place? It would be
DS> easy to do so with the values, but I'm not sure about the keys.

the values function in recent perls returns aliases to the values (which
are normal perl scalars) of the hash so you can directly mung them. but
the keys aren't normal perl values and so you can't take a reference or
alias to them. you have to deal with them indirectly via the hash's
interface which is what those two solutions do.

uri

--
Uri Guttman ------ (E-Mail Removed) -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      01-31-2006
Uri Guttman <(E-Mail Removed)> wrote in
news(E-Mail Removed):

>>>>>> "ASU" == A Sinan Unur <(E-Mail Removed)> writes:

>
> ASU> my %h = map { $_ => 1 } ('aaa' .. 'zzz');
>
> ASU> cmpthese -1, {
> ASU> map => sub { %h = map { uc $_ => $h{$_} } keys %h },
> ASU> for => sub { $h{uc $_} = delete $h{$_} for keys %h; },
> ASU> };
>
> this benchmark has a common problem in that you don't set up the hash
> the same way for each run.


I actually thought about this before posting.

> the first time you call either sub, the hash will have only
> upper case keys. now i doubt that uc will be faster or slower
> given any mix of input case


Which is why I decided not worry about it (in this case).

> but it still is wrong.


I am not sure it is that wrong.

> if the transform were something whose speed was data dependent,
> this benchmark would be very bogus.


Absolutely.

> the map one could be fixed just by assigning it to a different hash.
> the for one would need a fresh hash each time as it modifies it in
> place. so you would need to do the same work for each one and my best
> idea would be to copy the %h to %h2 inside each sub and use that as
> the input (and you can use it for the output of the map. also choosing
> a different output hash for the map could affect speed as well.
>
> this is just a small lesson on the difficulty of properly benchmarking
> apples and apples.


Do you meam I should use:

#!/usr/bin/perl

use warnings;
use strict;

use Benchmark qw( cmpthese );

my %h = map { $_ => 1 } ('aaa' .. 'zzz');

cmpthese -1, {
map => sub { my %h2 = %h; %h2 = map { uc $_ => $h{$_} } keys %h },
for => sub { my %h2 = %h; $h2{uc $_} = delete $h2{$_} for keys %h2; },
};
__END__

D:\Home\asu1\UseNet\clpmisc> s.pl
Rate map for
map 7.31/s -- -39%
for 12.0/s 64% --

Or, should I omit the my %h2 = %h in the 'map' version?

D:\Home\asu1\UseNet\clpmisc> s.pl
Rate for map
for 12.1/s -- -3%
map 12.4/s 3% --

I don't think the latter version is fair to 'for' though.

Sinan

--
A. Sinan Unur <(E-Mail Removed)>
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:
http://mail.augustmail.com/~tadmc/cl...uidelines.html
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
hash of hash of hash of hash in c++ rp C++ 1 11-10-2011 04:45 PM
Hash#select returns an array but Hash#reject returns a hash... Srijayanth Sridhar Ruby 19 07-02-2008 12:49 PM
transform hash key from string into symbol Old Echo Ruby 7 01-02-2008 12:50 PM
In 'HashMap.put', "if (e.hash == hash && eq(k, e.key))" ? Red Orchid Java 3 01-30-2006 07:04 PM
blocking I/O with javax.xml.parsers.DocumentBuilder.parse() and javax.xml.transform.Transformer.transform() jazzdman@gmail.com Java 1 03-27-2005 06:56 AM



Advertisments