keys %hash without destory element order

F

Fei Liu

Hi Group, what should I do to keep the order of elements in a hash when
I iterate through it? Example:

Code:
%hash = (a, b, c, d, e, f, ca, cb);
foreach (keys %hash){ print "$_ => $hash{$_}\n"; }

Result:
e => f
c => d
a => b
ca => cb

How to make it output:
a => b
c => d
e => f
ca => cb

Thanks,
 
J

John W. Krahn

Fei said:
Hi Group, what should I do to keep the order of elements in a hash when
I iterate through it? Example:

Code:

Don't forget to include:

use warnings;
use strict;
%hash = (a, b, c, d, e, f, ca, cb);

Don't use barewords, quote your strings.

my %hash = ( 'a', 'b', 'c', 'd', 'e', 'f', 'ca', 'cb' );

Or:

my %hash = qw( a b c d e f ca cb );
foreach (keys %hash){ print "$_ => $hash{$_}\n"; }

Result:
e => f
c => d
a => b
ca => cb

How to make it output:
a => b
c => d
e => f
ca => cb

my %hash = qw( a b c d e f ca cb );
my @order = qw( a c e ca );

for my $key ( @order ) {
print "$key => $hash{$key}\n";
}




John
 
D

Dr.Ruud

Fei Liu schreef:
Hi Group, what should I do to keep the order of elements in a hash
when I iterate through it? Example:

Code:
%hash = (a, b, c, d, e, f, ca, cb);
foreach (keys %hash){ print "$_ => $hash{$_}\n"; }

Result:
e => f
c => d
a => b
ca => cb

How to make it output:
a => b
c => d
e => f
ca => cb

If your order is an algorithm, like: "first by length, then
alphabetical", then you can use sort.
 
G

gf

John said:
my %hash = qw( a b c d e f ca cb );
my @order = qw( a c e ca );

for my $key ( @order ) {
print "$key => $hash{$key}\n";
}

I tend to go at it a bit backwards to this...

my @order = qw( a c e ca);
my %hash;
@hash{@order} = qw(b d f cb);

Or just for a bit easier maintenance because the keys and values are
easily aligned and checked visually...

my @keys = qw( a c e ca );
my @values = qw( b d f cb );
my %hash;
@hash{@keys} = @values;

Then iterate through @keys however is desired and do the lookups in
%hash as normal. It's not much different, but on hashes where you've
absolutely got to retrieve keys in a certain order it works well.

For big hashes it's unweildy to maintain though so I use an alternative
of a dynamically built hash of hashes with the secondary hash
containing a key that is the order to use and look at that value in an
inline sort {}. It's a bit uglier for static lists of values but works
nicely if you don't know how many elements there's going to be.

Shootin' from the hip here...

use strict;
use warnings;

my %hash;
my $order = 0;

# gather some arbitrary data...
foreach ( 'A' .. 'Z' )
{
$hash{$_} = {
'order' => $order++, # ...remember the order...
'value' => ord($_) # ...remember the related value...
};
}

# now walk through the keys, put them back in order...
foreach ( sort { $hash{$a}->{'order'} <=> $hash{$b}->{'order'} } keys
%hash )
{
print $_, ' => ', $hash{$_}->{'value'}, "\n"; # ...and print the
values.
}


Or something like that.
 
B

Bart Lateur

Paul said:
If you'd like to use a structure that pretends to be a hash, but also
has an order, download the Tie::IxHash module from CPAN

Or its XS sibling, Tie::Hash::Indexed.
 

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

Members online

Forum statistics

Threads
473,744
Messages
2,569,479
Members
44,900
Latest member
Nell636132

Latest Threads

Top