joec_ has asked for the wisdom of the Perl Monks concerning the following question:

Hi, i have a hash of names and random numbers. What i would like to do is end up with a full print of the list and other lists (more hashes maybe?) like this:

Full list:
-------
Greg, 1111
Caroline,2222
Joe,3333
...
Edited lists:
-----------
Caroline, 2222
Joe, 3333
....
* Note removal of first element

-----------
Greg, 1111
Joe, 3333
....
* Note removal of second element

The code i have so far is:

#!/usr/bin/perl use strict; use warnings; my $range=8999; my $min = 1000; my @names = qw(Greg Caroline Joe Dom Mary Gerard Mark Clare Adam Damia +n Debbie Conor Cassie John Jane Mike); my %hash; foreach my $n (@names){ my $r = int(rand($range))+$min; $hash{$n}=$r; }

I would also like the lists to match the order of the @names array
The logic is eluding me but i can guess that its really simple.

Any suggestions appreciated.

Thanks
Joe

Replies are listed 'Best First'.
Re: Print hash except first value
by ww (Archbishop) on Dec 21, 2008 at 02:31 UTC
    Re your use of a hash and your desire to omit the "first" element: You should understand that the order of a hash's elements is not defined; that is, the order in which you create the elements will be the order in which the elements are processed only by chance, absent use of sort or a Tie::... modules.
      While the order of hash elements is not defined, for a given hash, the keys will be returned in a consistent order as long as the hash is not altered. The OP's desire to generate the n possible lists of n - 1 elements (key/value pairs) from a list of n elements is consistent with the use of a hash.
Re: Print hash except first value
by ikegami (Patriarch) on Dec 20, 2008 at 22:20 UTC

    Some alternatives:

    my $first = 1; for my $n (sort { $hash{$a} <=> $hash{$b} } keys %hash){ if ($first) { $first = 0; next; } ... }
    my @names_by_val = sort { $hash{$a} <=> $hash{$b} } keys %hash; shift(@names_by_val); for my $n (@names_by_val) { ... }
    my @names_by_val = sort { $hash{$a} <=> $hash{$b} } keys %hash; for my $n (@names_by_val[1..$#names]) { ... }

    A hash isn't needed at all.

    my %hash; foreach my $n (@names){ my $r = int(rand($range))+$min; $hash{$n}=$r; } my @names_by_val = sort { $hash{$a} <=> $hash{$b} } keys %hash;

    can be replaced with

    use List::Util qw( shuffle ); my @shuffled_names = shuffle @names;

    Update: Doesn't answer the question.

      Here's a way using two arrays. You can iterate over the index of the elements in each array while preserving the order of the @names.

      my @names = qw(Greg Caroline Joe Dom Mary Gerard Mark Clare Adam Damia +n Conor Cassie John Jane Mike); my $max_rand = 8999; my $min_rand = 0; my @random_array = map{ int(rand($max_rand + 1)) + $min_rand } @names; foreach my $index (0..$#names) { print "$names[$index], $random_array[$index]\n"; }

      In addition, you could easily not print a line based on its index number. For example inside the print loop add:

      my $skip_index = 0; next if $index == $skip_index;
      thanks for the quick reply, what does each section of your code do?
        They iterate over the (keys of the) hash, skipping the first one

        Update: ...which I now see isn't what you asked. In fact, I don't know what you are trying to do. I don't see what the hash has to do with anything. As best as I can tell, you want a variation of

        for my $skip (0..$#names) { print("-------\n"); for my $i (0..$#names) { next if $i == $skip; my $n = $names[$i]; print("$n, $hash{$n}\n"); } print("* Note removal of element $skip\n"); print("\n"); }