[newbie] printing a hash

Discussion in 'Perl Misc' started by David, Feb 28, 2004.

  1. David

    David Guest

    I can't really visualise what's going on in this code. We're simply reading
    splitting each line of a file and saving the result in a hash, right?

    How can I print the contents of the hash?

    open(FILE, 'orig.txt') or die "Can't open orig.txt: $!";

    my @fields = qw/a b c d e f g h i j k/;
    my $record = <FILE>;

    while (<FILE>) {
    chomp $record;
    my %hash;
    @hash{@fields} = split(/\t/, $record);
    }

    print "$. records processed.\n";

    close FILE;
     
    David, Feb 28, 2004
    #1
    1. Advertising

  2. Also sprach David:

    > I can't really visualise what's going on in this code. We're simply reading
    > splitting each line of a file and saving the result in a hash, right?
    >
    > How can I print the contents of the hash?
    >
    > open(FILE, 'orig.txt') or die "Can't open orig.txt: $!";
    >
    > my @fields = qw/a b c d e f g h i j k/;
    > my $record = <FILE>;
    >
    > while (<FILE>) {
    > chomp $record;
    > my %hash;
    > @hash{@fields} = split(/\t/, $record);
    > }


    This makes no sense. You read the first record from FILE into $record
    and then loop over the rest of the file, but without ever assigning the
    next record to $record. The above should read:

    # drop this:
    # my $record = <FILE>;

    while (<FILE>) {
    chomp;
    my %hash;
    @hash{ @fields } = split /\t/, $_;
    # do something with %hash now as
    # it will be recreated each
    # iteration
    }

    > print "$. records processed.\n";
    >
    > close FILE;


    Tassilo
    --
    $_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
    pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
    $_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval
     
    Tassilo v. Parseval, Feb 28, 2004
    #2
    1. Advertising

  3. "David" <> writes:

    > I can't really visualise what's going on in this code. We're simply
    > reading splitting each line of a file and saving the result in a
    > hash, right?


    Yep. The hash keys are the letters [a-k], and the hash values are the
    fields from a line the file. The fields in the file are separated by
    tabs.

    > How can I print the contents of the hash?
    >
    > open(FILE, 'orig.txt') or die "Can't open orig.txt: $!";
    >
    > my @fields = qw/a b c d e f g h i j k/;


    These next two lines appear to be slightly wrong:
    > my $record = <FILE>;


    Delete the above line, and...

    >
    > while (<FILE>) {


    change the above line to:

    while (my $record = <FILE>) {

    That way, $record will be updated every time around the loop, instead
    of only once before the loop.

    > chomp $record;
    > my %hash;
    > @hash{@fields} = split(/\t/, $record);


    # print the hash
    my @keys = keys %hash;
    foreach my $key (@keys) {
    print("key: $key => value: $hash{$key}\n");
    }
    print("-" x 72, "\n");

    > }
    >
    > print "$. records processed.\n";
    >
    > close FILE;



    --
     
    Beable van Polasm, Feb 28, 2004
    #3
  4. David

    Iain Guest

    "David" <> wrote in
    news:40406278$0$5871$:

    > I can't really visualise what's going on in this code. We're simply
    > reading splitting each line of a file and saving the result in a
    > hash, right?
    >
    > How can I print the contents of the hash?


    As you will no doubt learn very rapidly if you read this group, you
    ought to start every Perl program with the incantation:

    use strict;
    use warnings;

    which allows Perl to help you by spitting out lots of useful information
    about possible mistakes in your program.

    > open(FILE, 'orig.txt') or die "Can't open orig.txt: $!";
    >
    > my @fields = qw/a b c d e f g h i j k/;
    > my $record = <FILE>;


    <> in scalar context returns a single line from a file, so this will
    read the first line of the contents of FILE into $record. It's not
    really necessary in this instance (see below).

    > while (<FILE>) {


    Whereas <> as the sole condition for a while loop is magic, and is
    shorthand for:

    while ( $_ = <FILE> ) {

    So in this case I suspect you would be better off with the condition

    while ( my $record = <FILE> ) {

    and then you can eliminate the initial 'my $record = <FILE>;' line
    above.

    > chomp $record;


    This will work the first time around the loop, but in your original
    program you're not updating the value of $record anywhere, making it a
    fairly worthless statement.

    > my %hash;


    You are using my() within a block (the {..} construct of the while
    loop). This will lexically scope the variable to a *single iteration* of
    the loop. In other words, you are creating a new %hash variable every
    time you read another line from FILE. And losing it almost immediately.
    Do you really want a new hash for each line of the file, or are you
    trying to aggregate the data in some form?

    > @hash{@fields} = split(/\t/, $record);


    You are trying to assign to a hash slice of exactly 11 keys. Is this
    what you want -- in other words, can you guarantee that each line of
    FILE contains 11 items each separated by a single tab character?

    > }
    >
    > print "$. records processed.\n";


    This works, but it's probably clearer to use an explicit line-counter
    variable. That will also have the advantage that it won't get reset if
    you close() the file.

    > close FILE;
    >
    >


    And I haven't yet touched upon how you might view the contents of your
    hash, but see the following. Note that it probably isn't doing what you
    expect or want (unles you really DO want the hash to be overwritten on
    each iteration), but it should give you a clearer idea of what's going
    on.



    #!perl

    use strict;
    use warnings;

    open(FILE, 'orig.txt') or die "Can't open orig.txt: $!";

    my @fields = qw/a b c d e f g h i j k/;

    my $lines = 0;
    while (my $record =<FILE>) {
    chomp $record;
    my %hash;
    @hash{@fields} = split(/\t/, $record);
    $lines++;

    print "After $lines lines, hash contains:\n";
    # A simple way to print the contents of a hash:
    foreach ( sort keys %hash ) {
    print " $_ => $hash{$_}\n";
    }

    }

    close FILE;
    print "$lines records processed.\n";


    --
    # Iain | PGP mail preferred: 9.co.uk/misc/iain.asc
    ($=,$,)=split m$"13/$,qq;13"13/tl\.rnh r HITtahkPctacriAneeeusaoJ;;
    for(@==sort@$=split m,,,$,){$..=$$[$=];$$=$=[$=];$@=1;$@++while$=[--$=
    ]eq$$&&$=>=$?;$==$?;for(@$){$@--if$$ eq$_;;last if!$@;$=++}}print$..$/
     
    Iain, Feb 28, 2004
    #4
  5. Iain <9.co.uk> wrote:

    >> while (<FILE>) {

    >
    > Whereas <> as the sole condition for a while loop is magic, and is
    > shorthand for:
    >
    > while ( $_ = <FILE> ) {



    It is actually shorthand for:

    while ( defined($_ = <FILE>) ) {


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Feb 28, 2004
    #5
  6. David <> wrote:

    > I can't really visualise what's going on in this code.



    > my @fields = qw/a b c d e f g h i j k/;

    [snip]
    > @hash{@fields} = split(/\t/, $record);



    I'll guess that this is what is throwing you (despite the many
    other problems in your program).

    That is a "hash slice". Read all about it in the "Slices" section of:

    perldoc perldata


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Feb 28, 2004
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jon B
    Replies:
    7
    Views:
    7,560
    =?Utf-8?B?SmFzb25DaG9p?=
    Jan 30, 2006
  2. JustSomeGuy
    Replies:
    13
    Views:
    519
    msalters
    Dec 9, 2004
  3. iffy agbim
    Replies:
    1
    Views:
    114
    Mark Andrews
    May 24, 2004
  4. rp
    Replies:
    1
    Views:
    556
    red floyd
    Nov 10, 2011
  5. Srijayanth Sridhar
    Replies:
    19
    Views:
    640
    David A. Black
    Jul 2, 2008
Loading...

Share This Page