Having Trouble Accessing Hash with Two "keys"

Discussion in 'Perl Misc' started by R^3, Nov 20, 2005.

  1. R^3

    R^3 Guest

    For some reason, I cannot access a hash with two keys. When I attempt
    to print its contents, all I get is whitespace.

    If I try to print "$counts{'french',4}"; I get the proper output, but
    when I try "$counts{$building,$i}; all I get is whitespace. How can I
    fix this????

    #!/usr/bin/perl

    open (OUT,">data.dat");

    my %hash = ();
    @masterBuildings = ();
    while ($line = <STDIN>)
    {
    if ($line =~ m/\(Info\): Station (\w+) (Rea|A)ssociated/){
    @fields = split " ", $line;
    $index = $fields[2];
    $building = $fields[5];
    $building =~ s/[0-9]+-(wb|ap)$//;
    $counts{$building,$index} += 1;
    push(@masterBuildings,$building);
    }

    }
    @Buildings = &uniq(@masterBuildings);

    foreach $building (@Buildings) {
    #$building = "'" . $building . "'";
    $i = 2;
    while ($i < 7) {
    print "$counts{$building, $i}\n";
    #does not work, but $counts{'french',4} does.
    $i += 1;
    }
    }


    sub uniq {
    local(@words) = @_; # local copy of array
    local(%MARK); # temporary associative array
    grep($MARK{$_}++, @words); # counts each occurance
    (ignored)
    keys %MARK; # return the unique elements

    }
     
    R^3, Nov 20, 2005
    #1
    1. Advertising

  2. R^3

    Toni Erdmann Guest

    R^3 wrote:
    > For some reason, I cannot access a hash with two keys. When I attempt
    > to print its contents, all I get is whitespace.
    >
    > If I try to print "$counts{'french',4}"; I get the proper output, but
    > when I try "$counts{$building,$i}; all I get is whitespace. How can I
    > fix this????
    >


    You're using a hash with one key that consists of two strings.

    try: $counts{'french'}{'4'}

    Toni
     
    Toni Erdmann, Nov 20, 2005
    #2
    1. Advertising

  3. R^3 wrote:

    > For some reason, I cannot access a hash with two keys.


    Could that be because there's no such thing in Perl?

    I Perl there are two ways to emmulate multi-keyed associative arrays.

    Method 1 (from Perl4) join the keys using a non-printing character as a
    delimiter. (This is what you've done).

    Method 2 (usually the preferred method in Perl5) use a hash of
    references to anonymous hashes. This is often abberviated to
    hash-of-hash or HoH.

    Are you using Perl5? Everything about your code seems to imply you have
    written it to run on Perl4. Appart that is for one line with a "my" in
    it that implies you must have Perl5.

    > When I attempt
    > to print its contents, all I get is whitespace.


    Do you? Are you sure?

    > If I try to print "$counts{'french',4}"; I get the proper output, but
    > when I try "$counts{$building,$i}; all I get is whitespace.


    Whitespace is not the same thing as nothing. Whitespace is a string
    made up from spaces, tabs, carriage returns, linefeeds and formfeeds.

    > How can I
    > fix this????
    >
    > #!/usr/bin/perl
    >
    > open (OUT,">data.dat");


    You forgot to check that succeded.

    > my %hash = ();


    There's no need to explicitly make agregates empty - they start out that
    way. Why do you delare a variable you never use?

    > @masterBuildings = ();


    There's no need to explicitly make agregates empty - they start out that
    way. You forgot my() - if you'd put "use strict" at the top of your
    script perl would have spotted this for you.

    > while ($line = <STDIN>)


    You forgot my() - if you'd put "use strict" at the top of your script
    perl would have spotted this for you.

    > {
    > if ($line =~ m/\(Info\): Station (\w+) (Rea|A)ssociated/){
    > @fields = split " ", $line;


    You forgot my() - if you'd put "use strict" at the top of your script
    perl would have spotted this for you.

    It would probably been more readble to use capturing rather than split.

    > $index = $fields[2];


    You forgot my() - if you'd put "use strict" at the top of your script
    perl would have spotted this for you.

    > $building = $fields[5];


    You forgot my() - if you'd put "use strict" at the top of your script
    perl would have spotted this for you.

    > $building =~ s/[0-9]+-(wb|ap)$//;
    > $counts{$building,$index} += 1;


    +=1 is more conventionally written ++

    > push(@masterBuildings,$building);
    > }
    >
    > }
    > @Buildings = &uniq(@masterBuildings);


    Why is there an & there? If you don't know what the & does then you
    doen't want it.

    > foreach $building (@Buildings) {


    You forgot my() - if you'd put "use strict" at the top of your script
    perl would have spotted this for you.

    > #$building = "'" . $building . "'";
    > $i = 2;


    You forgot my() - if you'd put "use strict" at the top of your script
    perl would have spotted this for you.

    > while ($i < 7) {


    It would be more conventional to write:

    for my $i ( 2 .. 6 )

    > print "$counts{$building, $i}\n";
    > #does not work, but $counts{'french',4} does.


    What reason do you have to suppose that $building ever has the value
    'french'.

    Perhaps you should insert a diagnostic:

    print "<<<$building>>>\n";

    It's always a good idea to print something on the end like this in case
    there's any whitespace on the end of the value of $building.

    > $i += 1;
    > }
    > }
    >
    >
    > sub uniq {
    > local(@words) = @_; # local copy of array


    You should not localize a global varialble when a lexcal variable would
    do the job perfectly well.

    > local(%MARK); # temporary associative array


    Avoid comments that contain no information.

    > grep($MARK{$_}++, @words); # counts each occurance
    > (ignored)


    Do not use grep() or map() in a void context, use for. That's what
    it's, er..., for:

    $MARK{$_}++ for @words;

    > keys %MARK; # return the unique elements
    >
    > }
    >
     
    Brian McCauley, Nov 20, 2005
    #3
  4. "R^3" <> wrote in
    news::

    > For some reason, I cannot access a hash with two keys. When I attempt
    > to print its contents, all I get is whitespace.
    >
    > If I try to print "$counts{'french',4}"; I get the proper output, but


    Could you please explain what $counts{'french', 4} means? I am not
    familiar with the notation, and it seems to do something, but I am at
    a loss as to why you cannot use $counts{french}{4}?

    D:\Home\asu1\UseNet\clpmisc> cat tt.pl
    #!/usr/bin/perl

    use strict;
    use warnings;

    my %hash;
    $hash{qw(a b)} = 1;
    $hash{a}{b} = 1;

    use Data::Dumper;
    print Dumper \%hash;

    D:\Home\asu1\UseNet\clpmisc> tt
    $VAR1 = {
    'a' => {
    'b' => 1
    },
    'a?b' => 1
    };

    > #!/usr/bin/perl


    use strict;
    use warnings;

    > open (OUT,">data.dat");


    Always check the return value of open to see if it succeded. Also, why are
    you opening this file? You don't use it below.

    > my %hash = ();
    > @masterBuildings = ();


    You don't need to explicitly initialize these variables:

    my (%hash, @masterBuildings);

    > while ($line = <STDIN>)


    When you are posting here, please use the DATA file handle as described
    in the posting guidelines for this group.

    > {
    > if ($line =~ m/\(Info\): Station (\w+) (Rea|A)ssociated/){
    > @fields = split " ", $line;
    > $index = $fields[2];
    > $building = $fields[5];
    > $building =~ s/[0-9]+-(wb|ap)$//;


    You need to make a decision here: Are you going to parse based on a
    regular expression or are you just going to split the input line?
    Here, you first use a capturing regex, then proceed to split. Since
    we don't know what your input looks like, it is very hard to comment
    on what you are doing.

    ....

    > sub uniq {
    > local(@words) = @_; # local copy of array
    > local(%MARK); # temporary associative array
    > grep($MARK{$_}++, @words); # counts each occurance
    > (ignored)
    > keys %MARK; # return the unique elements


    I seriously doubt you want to use local here:

    <URL:http://perl.plover.com/FAQs/Namespaces.html>

    Besides, it is far easier to write this in the following way:

    sub unique_values { my %tmp = map { $_ => 1 } @_; keys %tmp; }

    Of course, I would have used List::MoreUtils::uniq:

    <URL:http://search.cpan.org/~vparseval/List-MoreUtils-0.16/lib/List/MoreUtils.pm>

    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Nov 20, 2005
    #4
  5. Brian McCauley <> wrote in news:dlqh9h$p11$1
    @slavica.ukpost.com:

    >
    > R^3 wrote:
    >
    >> For some reason, I cannot access a hash with two keys.

    >
    > Could that be because there's no such thing in Perl?
    >
    > I Perl there are two ways to emmulate multi-keyed associative arrays.
    >
    > Method 1 (from Perl4) join the keys using a non-printing character as
    > a delimiter. (This is what you've done).



    Thank you for the explanation. I had not seen that before.

    Sinan

    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Nov 20, 2005
    #5
  6. R^3

    R^3 Guest

    Thanks. I tried to implement an HoH again, and this time I was able to
    get it to work! Thanks!
     
    R^3, Nov 23, 2005
    #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. rp
    Replies:
    1
    Views:
    539
    red floyd
    Nov 10, 2011
  2. Xeno Campanoli
    Replies:
    16
    Views:
    268
    Martin DeMello
    Aug 25, 2005
  3. Malik Yousef

    Sort Hash o Hash accordint to two keys

    Malik Yousef, May 6, 2004, in forum: Perl Misc
    Replies:
    9
    Views:
    197
    Uri Guttman
    May 7, 2004
  4. Malik Yousef

    Sort Hash o Hash accordint to two keys

    Malik Yousef, May 6, 2004, in forum: Perl Misc
    Replies:
    0
    Views:
    104
    Malik Yousef
    May 6, 2004
  5. Replies:
    12
    Views:
    237
    J├╝rgen Exner
    Jul 6, 2013
Loading...

Share This Page