Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Having Trouble Accessing Hash with Two "keys"

Reply
Thread Tools

Having Trouble Accessing Hash with Two "keys"

 
 
R^3
Guest
Posts: n/a
 
      11-20-2005
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

}

 
Reply With Quote
 
 
 
 
Toni Erdmann
Guest
Posts: n/a
 
      11-20-2005
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
 
Reply With Quote
 
 
 
 
Brian McCauley
Guest
Posts: n/a
 
      11-20-2005

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
>
> }
>

 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      11-20-2005
"R^3" <(E-Mail Removed)> wrote in
news:(E-Mail Removed) oups.com:

> 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:umper;
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 <(E-Mail Removed)>
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:
http://mail.augustmail.com/~tadmc/cl...uidelines.html

 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      11-20-2005
Brian McCauley <(E-Mail Removed)> 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 <(E-Mail Removed)>
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:
http://mail.augustmail.com/~tadmc/cl...uidelines.html

 
Reply With Quote
 
R^3
Guest
Posts: n/a
 
      11-23-2005
Thanks. I tried to implement an HoH again, and this time I was able to
get it to work! Thanks!

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
hash of hash of hash of hash in c++ rp C++ 1 11-10-2011 04:45 PM
Hash#select returns an array but Hash#reject returns a hash... Srijayanth Sridhar Ruby 19 07-02-2008 12:49 PM
Having trouble with internal users accessing the Internet using NAT novatech1989@yahoo.com Cisco 4 01-23-2007 02:05 PM
OT Anyone having trouble accessing their Tripod accounts today? RobMac DVD Video 2 01-02-2007 10:47 PM
Anybody Else Having Trouble Accessing DVDTalk.com today? djskyler DVD Video 3 01-15-2005 11:52 PM



Advertisments