FAQ
Hello All,

I am doing some file reading operation, and parsing the data(its a CSV file) with a hash reference and then intend to store it in a record.

something like:

loop: until file ends;
$hashref->{'A'}=$filehandle->{'Action'};
$hashref->{'B'}= $filehandle->{'Name'};
$hashref->{'C'}= $filehandle->{'System'};
$hashref->{'D'}=($filehandle->{'Price'});

$recordref->{$hashref->{'B'}}= $hashref;

loop : ends

Here Action, Name,System,price are the CSV headers.

Now, when the first line is read, the details are parsed and stored in the $recordref as a hash reference. Now when the loop iterates, and goes to the second line. The first line contents are lost. Because the hash reference now points to the newer data.

How do I overcome this?
More importantly do we have a push equivalent for hash of hashes?

Soham


Send free SMS to your Friends on Mobile from your Yahoo! Messenger. Download Now! http://messenger.yahoo.com/download.php

Search Discussions

  • Jim Gibson at Oct 9, 2009 at 5:31 am

    At 10:14 PM -0700 10/8/09, Soham Das wrote:
    Hello All, I am doing some file reading operation, and parsing the
    data(its a CSV file) with a hash reference and then intend to store
    it in a record. something like: loop: until file ends;
    $hashref->{'A'}=$filehandle->{'Action'};
    $hashref->{'B'}= $filehandle->{'Name'};
    $hashref->{'C'}= $filehandle->{'System'};
    $hashref->{'D'}=($filehandle->{'Price'});
    $recordref->{$hashref->{'B'}}= $hashref; loop : ends

    You are better off including some actual Perl code, including some sample data.
    Here Action, Name,System,price are the CSV headers. Now, when the
    first line is read, the details are parsed and stored in the
    $recordref as a hash reference. Now when the loop iterates, and goes
    to the second line. The first line contents are lost. Because the
    hash reference now points to the newer data. How do I overcome this?
    More importantly do we have a push equivalent for hash of hashes?
    No. Unless each record has a unique key, you are better off using an
    array of hashes, rather than a hash of hashes. Of course, you could
    use the line number as a unique key, but an array would be more
    efficient.

    --
    Jim Gibson
    Jim@Gibson.org
  • Soham Das at Oct 9, 2009 at 5:33 am
    The code:



    ________________________________
    From: Jim Gibson <jimsgibson@gmail.com>
    To: beginners@perl.org
    Sent: Fri, 9 October, 2009 11:00:55 AM
    Subject: Re: Building a record on the fly via hash of hashes
    At 10:14 PM -0700 10/8/09, Soham Das wrote:
    Hello All, I am doing some file reading operation, and parsing the data(its a CSV file) with a hash reference and then intend to store it in a record. something like: loop: until file ends; $hashref->{'A'}=$filehandle->{'Action'}; $hashref->{'B'}= $filehandle->{'Name'}; $hashref->{'C'}= $filehandle->{'System'}; $hashref->{'D'}=($filehandle->{'Price'}); $recordref->{$hashref->{'B'}}= $hashref; loop : ends

    You are better off including some actual Perl code, including some sample data.
    Here Action, Name,System,price are the CSV headers. Now, when the first line is read, the details are parsed and stored in the $recordref as a hash reference. Now when the loop iterates, and goes to the second line. The first line contents are lost. Because the hash reference now points to the newer data. How do I overcome this? More importantly do we have a push equivalent for hash of hashes?
    No. Unless each record has a unique key, you are better off using an array of hashes, rather than a hash of hashes. Of course, you could use the line number as a unique key, but an array would be more efficient.

    -- Jim Gibson
    Jim@Gibson.org

    -- To unsubscribe, e-mail: beginners-unsubscribe@perl.org
    For additional commands, e-mail: beginners-help@perl.org
    http://learn.perl.org/


    Yahoo! India has a new look. Take a sneak peek http://in.yahoo.com/trynew
  • Soham Das at Oct 9, 2009 at 5:36 am
    The Code:

    use strict;
    use warnings;
    use Tie::Handle::CSV;

    my $qbook = Tie::Handle::CSV->new('C:\Documents and Settings\Soham Das\Desktop\Quotes.csv',header=>1);
    my $tradebook = Tie::Handle::CSV->new('C:\Documents and Settings\Soham Das\Desktop\Transactions.csv',header=>1);

    my $dailytrade={};
    my $portfolio={};
    my $singletrade={};
    while(my $mktdates =<$qbook>)
    {
    while(my $trades=<$tradebook>)
    {
    if($trades->{'Date'} eq $mktdates->{'Date'})
    {
    $singletrade->{'Action'}=$trades->{'Action'};
    $singletrade->{'Scrip'}= $trades->{'Scrip'};
    $singletrade->{'Shares'}= $trades->{'Shares'};
    $singletrade->{'Price'}=($trades->{'Price'})*1.00845;

    $dailytrade->{$singletrade->{'Scrip'}}= $singletrade;
    # print $dailytrade->{$singletrade->{'Scrip'}}->{'Price'},"\n";
    }
    #Update the portfolio

    }
    }
    close $qbook ;
    close $tradebook;

    Soham

    P.S: apologies for the previous mail being a blank mail, it was a mistake




    ________________________________
    From: Soham Das <sohamdas@yahoo.co.in>
    To: beginners@perl.org
    Sent: Fri, 9 October, 2009 11:02:51 AM
    Subject: Re: Building a record on the fly via hash of hashes




    The code:



    ________________________________
    From: Jim Gibson <jimsgibson@gmail.com>
    To: beginners@perl.org
    Sent: Fri, 9 October, 2009 11:00:55 AM
    Subject: Re: Building a record on the fly via hash of hashes
    At 10:14 PM -0700 10/8/09, Soham Das wrote:
    Hello All, I am doing some file reading operation, and parsing the data(its a CSV file) with a hash reference and then intend to store it in a record. something like: loop: until file ends; $hashref->{'A'}=$filehandle->{'Action'}; $hashref->{'B'}= $filehandle->{'Name'}; $hashref->{'C'}= $filehandle->{'System'}; $hashref->{'D'}=($filehandle->{'Price'}); $recordref->{$hashref->{'B'}}= $hashref; loop : ends

    You are better off including some actual Perl code, including some sample data.
    Here Action, Name,System,price are the CSV headers. Now, when the first line is read, the details are parsed and stored in the $recordref as a hash reference. Now when the loop iterates, and goes to the second line. The first line contents are lost. Because the hash reference now points to the newer data. How do I overcome this? More importantly do we have a push equivalent for hash of hashes?
    No. Unless each record has a unique key, you are better off using an array of hashes, rather than a hash of hashes. Of course, you could use the line number as a unique key, but an array would be more efficient.

    -- Jim Gibson
    Jim@Gibson.org

    -- To unsubscribe, e-mail: beginners-unsubscribe@perl.org
    For additional commands, e-mail: beginners-help@perl.org
    http://learn.perl.org/



    ________________________________
    Now, send attachments up to 25MB with Yahoo! India Mail. Learn how.

    Send free SMS to your Friends on Mobile from your Yahoo! Messenger. Download Now! http://messenger.yahoo.com/download.php
  • John W. Krahn at Oct 9, 2009 at 6:27 am

    Soham Das wrote:
    The Code:

    use strict;
    use warnings;
    use Tie::Handle::CSV;

    my $qbook = Tie::Handle::CSV->new('C:\Documents and Settings\Soham Das\Desktop\Quotes.csv',header=>1);
    my $tradebook = Tie::Handle::CSV->new('C:\Documents and Settings\Soham Das\Desktop\Transactions.csv',header=>1);

    my $dailytrade={};
    my $portfolio={};
    my $singletrade={};
    You are declaring $singletrade in file scope from this point forward.

    while(my $mktdates =<$qbook>)
    {
    while(my $trades=<$tradebook>)
    {
    if($trades->{'Date'} eq $mktdates->{'Date'})
    {
    $singletrade->{'Action'}=$trades->{'Action'};
    $singletrade->{'Scrip'}= $trades->{'Scrip'};
    $singletrade->{'Shares'}= $trades->{'Shares'};
    $singletrade->{'Price'}=($trades->{'Price'})*1.00845;
    Because $singletrade is in file scope you are overwriting the same four
    keys each time you enter this if block. You need to restrict the scope
    of $singletrade to inside the inner while loop otherwise you are just
    copying the *same* hash reference to every key of $dailytrade.

    $dailytrade->{$singletrade->{'Scrip'}}= $singletrade;
    # print $dailytrade->{$singletrade->{'Scrip'}}->{'Price'},"\n";
    }
    #Update the portfolio

    }
    }
    close $qbook ;
    close $tradebook;
    You probably want something like this:

    use strict;
    use warnings;
    use Tie::Handle::CSV;

    my $qbook = Tie::Handle::CSV->new( 'C:\Documents and Settings\Soham
    Das\Desktop\Quotes.csv', header => 1 );
    my $tradebook = Tie::Handle::CSV->new( 'C:\Documents and Settings\Soham
    Das\Desktop\Transactions.csv', header => 1 );

    my %dailytrade;
    my %portfolio;
    while ( my $mktdates = <$qbook> ) {

    while ( my $trades = <$tradebook> ) {

    if ( $trades->{ Date } eq $mktdates->{ Date } ) {

    $dailytrade{ $trades->{ Scrip } } = {
    Action => $trades->{ Action },
    Scrip => $trades->{ Scrip },
    Shares => $trades->{ Shares },
    Price => $trades->{ Price } * 1.00845,
    };

    # print "$dailytrade{$trades->{Scrip}}{Price}\n";
    }
    #Update the portfolio

    }
    }

    close $qbook;
    close $tradebook;



    John
    --
    The programmer is fighting against the two most
    destructive forces in the universe: entropy and
    human stupidity. -- Damian Conway
  • Soham Das at Oct 9, 2009 at 7:56 am
    yes, I actually understood the problem but didnt have the "brainwave" to solve it. Now its much better.
    Yes indeed this will work much better.

    Thank you,
    John




    ________________________________
    From: John W. Krahn <jwkrahn@shaw.ca>
    To: Perl Beginners <beginners@perl.org>
    Sent: Fri, 9 October, 2009 11:57:09 AM
    Subject: Re: Building a record on the fly via hash of hashes

    Soham Das wrote:
    The Code:

    use strict;
    use warnings;
    use Tie::Handle::CSV;

    my $qbook = Tie::Handle::CSV->new('C:\Documents and Settings\Soham Das\Desktop\Quotes.csv',header=>1);
    my $tradebook = Tie::Handle::CSV->new('C:\Documents and Settings\Soham Das\Desktop\Transactions.csv',header=>1);

    my $dailytrade={};
    my $portfolio={};
    my $singletrade={};
    You are declaring $singletrade in file scope from this point forward.

    while(my $mktdates =<$qbook>)
    {
    while(my $trades=<$tradebook>)
    {
    if($trades->{'Date'} eq $mktdates->{'Date'})
    {
    $singletrade->{'Action'}=$trades->{'Action'};
    $singletrade->{'Scrip'}= $trades->{'Scrip'};
    $singletrade->{'Shares'}= $trades->{'Shares'};
    $singletrade->{'Price'}=($trades->{'Price'})*1.00845;
    Because $singletrade is in file scope you are overwriting the same four keys each time you enter this if block. You need to restrict the scope of $singletrade to inside the inner while loop otherwise you are just copying the *same* hash reference to every key of $dailytrade.

    $dailytrade->{$singletrade->{'Scrip'}}= $singletrade;
    # print $dailytrade->{$singletrade->{'Scrip'}}->{'Price'},"\n";
    }
    #Update the portfolio

    }
    }
    close $qbook ;
    close $tradebook;
    You probably want something like this:

    use strict;
    use warnings;
    use Tie::Handle::CSV;

    my $qbook = Tie::Handle::CSV->new( 'C:\Documents and Settings\Soham Das\Desktop\Quotes.csv', header => 1 );
    my $tradebook = Tie::Handle::CSV->new( 'C:\Documents and Settings\Soham Das\Desktop\Transactions.csv', header => 1 );

    my %dailytrade;
    my %portfolio;
    while ( my $mktdates = <$qbook> ) {

    while ( my $trades = <$tradebook> ) {

    if ( $trades->{ Date } eq $mktdates->{ Date } ) {

    $dailytrade{ $trades->{ Scrip } } = {
    Action => $trades->{ Action },
    Scrip => $trades->{ Scrip },
    Shares => $trades->{ Shares },
    Price => $trades->{ Price } * 1.00845,
    };

    # print "$dailytrade{$trades->{Scrip}}{Price}\n";
    }
    #Update the portfolio

    }
    }

    close $qbook;
    close $tradebook;



    John
    -- The programmer is fighting against the two most
    destructive forces in the universe: entropy and
    human stupidity. -- Damian Conway

    -- To unsubscribe, e-mail: beginners-unsubscribe@perl.org
    For additional commands, e-mail: beginners-help@perl.org
    http://learn.perl.org/


    From cricket scores to your friends. Try the Yahoo! India Homepage! http://in.yahoo.com/trynew
  • Soham Das at Oct 9, 2009 at 8:16 am
    Is this code better?
    I noticed, you missed some inverted commas,
    So, at the risk of being pedantic, I am appending the code:

    #!/usr/bin/perl
    use strict;
    use warnings;
    use Tie::Handle::CSV;

    my $qbook = Tie::Handle::CSV->new('C:\Documents and Settings\Soham Das\Desktop\Quotes.csv',header=>1);
    my $tradebook = Tie::Handle::CSV->new('C:\Documents and Settings\Soham Das\Desktop\Transactions.csv',header=>1);

    my $dailytrade={};
    my $portfolio={};
    while(my $mktdates =<$qbook>)
    {
    while(my $trades=<$tradebook>)
    {
    if($trades->{'Date'} eq $mktdates->{'Date'})
    {
    $dailytrade->{$trades->{'Scrip'}}={
    'Action'=$trades->{'Action'},
    'Scrip'= $trades->{'Scrip'},
    'Shares'= $trades->{'Shares'},
    'Price'=($trades->{'Price'})*1.00845,
    };
    }
    #Update the portfolio

    }
    }


    close $qbook ;
    close $tradebook;


    When I compile this, it gives me an error like this:

    Can't modify constant item in scalar assignment at Test.pl line 18, near "}";

    So for the sake of clarity I highlited the Line 18.

    'Action'=$trades->{'Action'},

    A bit of help in this, will be great!

    Soham




    ________________________________
    From: John W. Krahn <jwkrahn@shaw.ca>
    To: Perl Beginners <beginners@perl.org>
    Sent: Fri, 9 October, 2009 11:57:09 AM
    Subject: Re: Building a record on the fly via hash of hashes

    Soham Das wrote:
    The Code:

    use strict;
    use warnings;
    use Tie::Handle::CSV;

    my $qbook = Tie::Handle::CSV->new('C:\Documents and Settings\Soham Das\Desktop\Quotes.csv',header=>1);
    my $tradebook = Tie::Handle::CSV->new('C:\Documents and Settings\Soham Das\Desktop\Transactions.csv',header=>1);

    my $dailytrade={};
    my $portfolio={};
    my $singletrade={};
    You are declaring $singletrade in file scope from this point forward.

    while(my $mktdates =<$qbook>)
    {
    while(my $trades=<$tradebook>)
    {
    if($trades->{'Date'} eq $mktdates->{'Date'})
    {
    $singletrade->{'Action'}=$trades->{'Action'};
    $singletrade->{'Scrip'}= $trades->{'Scrip'};
    $singletrade->{'Shares'}= $trades->{'Shares'};
    $singletrade->{'Price'}=($trades->{'Price'})*1.00845;
    Because $singletrade is in file scope you are overwriting the same four keys each time you enter this if block. You need to restrict the scope of $singletrade to inside the inner while loop otherwise you are just copying the *same* hash reference to every key of $dailytrade.

    $dailytrade->{$singletrade->{'Scrip'}}= $singletrade;
    # print $dailytrade->{$singletrade->{'Scrip'}}->{'Price'},"\n";
    }
    #Update the portfolio

    }
    }
    close $qbook ;
    close $tradebook;
    You probably want something like this:

    use strict;
    use warnings;
    use Tie::Handle::CSV;

    my $qbook = Tie::Handle::CSV->new( 'C:\Documents and Settings\Soham Das\Desktop\Quotes.csv', header => 1 );
    my $tradebook = Tie::Handle::CSV->new( 'C:\Documents and Settings\Soham Das\Desktop\Transactions.csv', header => 1 );

    my %dailytrade;
    my %portfolio;
    while ( my $mktdates = <$qbook> ) {

    while ( my $trades = <$tradebook> ) {

    if ( $trades->{ Date } eq $mktdates->{ Date } ) {

    $dailytrade{ $trades->{ Scrip } } = {
    Action => $trades->{ Action },
    Scrip => $trades->{ Scrip },
    Shares => $trades->{ Shares },
    Price => $trades->{ Price } * 1.00845,
    };

    # print "$dailytrade{$trades->{Scrip}}{Price}\n";
    }
    #Update the portfolio

    }
    }

    close $qbook;
    close $tradebook;



    John
    -- The programmer is fighting against the two most
    destructive forces in the universe: entropy and
    human stupidity. -- Damian Conway

    -- To unsubscribe, e-mail: beginners-unsubscribe@perl.org
    For additional commands, e-mail: beginners-help@perl.org
    http://learn.perl.org/


    From cricket scores to your friends. Try the Yahoo! India Homepage! http://in.yahoo.com/trynew
  • Philip Potter at Oct 9, 2009 at 8:53 am

    2009/10/9 Soham Das <sohamdas@yahoo.co.in>:
    When I compile this, it gives me an error like this:

    Can't modify constant item in scalar assignment at Test.pl line 18, near "}";

    So for the sake of clarity I highlited the Line 18.

    'Action'=$trades->{'Action'},

    A bit of help in this, will be great!
    When perl gives you a line number, it's usually best to check the
    whole statement for errors, not just the line that it gives you; in
    this case the statement (from $dailytrade to the next semicolon ; ) is
    six lines long.

    The error message tells you that you can't modify a constant. It also
    mentions an assignment. Here's the full statement:
    $dailytrade->{$trades->{'Scrip'}}={
    'Action'=$trades->{'Action'},
    'Scrip'= $trades->{'Scrip'},
    'Shares'= $trades->{'Shares'},
    'Price'=($trades->{'Price'})*1.00845,
    };
    Looking at line 18 again:
    'Action'=$trades->{'Action'},
    Aha! You have an assignment (an = sign) which is trying to assign to
    'Action', a string constant. The error message was right! The solution
    is that you should have used a fat comma (a => sign) instead:
    'Action'=>$trades->{'Action'},
    This is the syntax used to create hash initialisers. If this confuses
    you, I suggest you read perldoc perldata, section "List value
    constructors". (If this confuses you too, then we need to have a chat
    about perldoc :) )

    Going back to the original statement:
    $dailytrade->{$trades->{'Scrip'}}={
    'Action'=$trades->{'Action'},
    'Scrip'= $trades->{'Scrip'},
    'Shares'= $trades->{'Shares'},
    'Price'=($trades->{'Price'})*1.00845,
    };
    You've made the same mistake in lines 19, 20 and 21. You should now be
    able to fix your code.

    Philip
  • Soham Das at Oct 9, 2009 at 9:27 am
    Philip,

    I think, the way you went about solving the problem {might be very trivial for you}, but laying bare your entire thought process, just taught something to me.

    Thanks and I am sure, many other beginners have picked it up from here.

    Yes,indeed after you pointed out to me, I (figuratively) kicked myself.

    Thanks

    Soham




    ________________________________
    From: Philip Potter <philip.g.potter@gmail.com>
    To: Soham Das <sohamdas@yahoo.co.in>
    Cc: beginners@perl.org
    Sent: Fri, 9 October, 2009 2:22:49 PM
    Subject: Re: Building a record on the fly via hash of hashes

    2009/10/9 Soham Das <sohamdas@yahoo.co.in>:
    When I compile this, it gives me an error like this:

    Can't modify constant item in scalar assignment at Test.pl line 18, near "}";

    So for the sake of clarity I highlited the Line 18.

    'Action'=$trades->{'Action'},

    A bit of help in this, will be great!
    When perl gives you a line number, it's usually best to check the
    whole statement for errors, not just the line that it gives you; in
    this case the statement (from $dailytrade to the next semicolon ; ) is
    six lines long.

    The error message tells you that you can't modify a constant. It also
    mentions an assignment. Here's the full statement:
    $dailytrade->{$trades->{'Scrip'}}={
    'Action'=$trades->{'Action'},
    'Scrip'= $trades->{'Scrip'},
    'Shares'= $trades->{'Shares'},
    'Price'=($trades->{'Price'})*1.00845,
    };
    Looking at line 18 again:
    'Action'=$trades->{'Action'},
    Aha! You have an assignment (an = sign) which is trying to assign to
    'Action', a string constant. The error message was right! The solution
    is that you should have used a fat comma (a => sign) instead:
    'Action'=>$trades->{'Action'},
    This is the syntax used to create hash initialisers. If this confuses
    you, I suggest you read perldoc perldata, section "List value
    constructors". (If this confuses you too, then we need to have a chat
    about perldoc :) )

    Going back to the original statement:
    $dailytrade->{$trades->{'Scrip'}}={
    'Action'=$trades->{'Action'},
    'Scrip'= $trades->{'Scrip'},
    'Shares'= $trades->{'Shares'},
    'Price'=($trades->{'Price'})*1.00845,
    };
    You've made the same mistake in lines 19, 20 and 21. You should now be
    able to fix your code.

    Philip

    --
    To unsubscribe, e-mail: beginners-unsubscribe@perl.org
    For additional commands, e-mail: beginners-help@perl.org
    http://learn.perl.org/


    From cricket scores to your friends. Try the Yahoo! India Homepage! http://in.yahoo.com/trynew
  • Paul Johnson at Oct 9, 2009 at 12:09 pm

    On Fri, Oct 09, 2009 at 02:57:44PM +0530, Soham Das wrote:

    Yes,indeed after you pointed out to me, I (figuratively) kicked myself.
    But those quotes are still ugly and unnecessary, as John showed.

    --
    Paul Johnson - paul@pjcj.net
    http://www.pjcj.net

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupbeginners @
categoriesperl
postedOct 9, '09 at 5:14a
activeOct 9, '09 at 12:09p
posts10
users5
websiteperl.org

People

Translate

site design / logo © 2021 Grokbase