keys %hash without destory element order

Discussion in 'Perl Misc' started by Fei Liu, Jan 11, 2007.

  1. Fei Liu

    Fei Liu Guest

    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,
     
    Fei Liu, Jan 11, 2007
    #1
    1. Advertisements

  2. Don't forget to include:

    use warnings;
    use strict;
    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 );
    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
     
    John W. Krahn, Jan 11, 2007
    #2
    1. Advertisements

  3. Fei Liu

    Paul Lalli Guest

    You're confused. There *is no order* in a hash. There's no order to
    keep.

    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

    Please see:
    http://search.cpan.org/~gsar/Tie-IxHash-1.21/lib/Tie/IxHash.pm
    perldoc -q cpan
    perldoc perlmodinstall

    Paul Lalli
     
    Paul Lalli, Jan 11, 2007
    #3
  4. There is no such thing as the order of elements in a hash.

    jue
     
    Jürgen Exner, Jan 12, 2007
    #4
  5. Fei Liu

    Dr.Ruud Guest

    Fei Liu schreef:
    If your order is an algorithm, like: "first by length, then
    alphabetical", then you can use sort.
     
    Dr.Ruud, Jan 12, 2007
    #5
  6. Fei Liu

    gf Guest

    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.
     
    gf, Jan 12, 2007
    #6
  7. Fei Liu

    Bart Lateur Guest

    Or its XS sibling, Tie::Hash::Indexed.
     
    Bart Lateur, Jan 12, 2007
    #7
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.