Home > Archive > PERL Beginners > June 2007 > Problems Assigning Unique Values to a Hash
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Problems Assigning Unique Values to a Hash
|
|
| campbell262@gmail.com 2007-06-26, 9:59 pm |
| I have a input file with thousands of lines in it. I use this input
file to produce multiply reports, one of which I only want to output
the unique product names.
For the sake of this forum I have shortened the input file from 2
elements down from 9, and only am concentrating on how to deal with
adding unique items to the hash and then printing them out.
I thought the code below would prevent me from adding items to my hash
if the key already existed but when I ran it didn't work. Is there
something I am missing here with the exists functionality? It seems
to be treating each line as if it is unique.
products.out
cellphone 52
cola 23
monitors 32
cellphone 23
mugs 1000
cellphone 52
Code:
open(FILE, "<products.out");
my(%hash)=undef;
while(<FILE> ) {
($product, $qty) = split /\|/, $_;
if (exists $hash{$product}){
#do nothing
}
else {
my %hash = ( $product => $qty);
print "The $product is unique\n";
}
}
close(FILE);
| |
| Tom Phoenix 2007-06-26, 9:59 pm |
| On 6/26/07, campbell262@gmail.com <campbell262@gmail.com> wrote:
> open(FILE, "<products.out");
So the input is called something ".out"? Okay, if you must, but you
should check the result of open with "or die".
> my(%hash)=undef;
And you should probably add "use strict" and "use warnings", to catch
things like this. The right side isn't an "empty value", it's a scalar
value called undef. As it is in a list context, that becomes a
one-element list. But hashes need lists of key-value pairs. You meant
this:
my(%hash) = ();
But that's really the same as this:
my %hash;
> my %hash = ( $product => $qty);
And here, you have declared a new variable named %hash. But what I
think you wanted was to assign to an element in the hash:
$hash{$product} = $qty; # add element to hash
Does that get you closer to your goal? Good luck with it!
--Tom Phoenix
Stonehenge Perl Traning
| |
| Paul Johnson 2007-06-26, 9:59 pm |
| On Tue, Jun 26, 2007 at 03:48:21PM -0700, Tom Phoenix wrote:
> Does that get you closer to your goal? Good luck with it!
Also, you are splitting on | when the data suggests you should split on
whitespace.
--
Paul Johnson - paul@pjcj.net
http://www.pjcj.net
| |
| Perl_power 2007-06-27, 9:59 pm |
| Tom,
I did make some changes but that actually is still causing me to
output each line while looping through the file instead of only adding
unique key value pairs to the hash. I can only guess I am overriding
the hash each time it loops? Also don't understand the line break I
am getting between the number and is unique.
So the input is: (I did mean to type a | when I wrote this post but
just didn't)
products.out
cellphone|52
cola|23
monitors|32
cellphone|23
mugs|1000
cellphone|52
Code:
open(FILE, "<products.out") or die "1. Can't open $FILE for reading:
$!. Stopped";
my(%hash);
while(<FILE> ) {
($product, $qty) = split /\|/, $_;
if (exists $hash{$product}){
#do nothing
}
else {
$hash{$product} = $qty;
print "The $product is unique\n";
}
}
Output:
The 52
is unique
The 23
is unique
The 32
is unique
The 23
is unique
The 1000
is unique
The 52
is unique
| |
| Chas Owens 2007-06-27, 9:59 pm |
| On 6/27/07, perl_power <campbell262@gmail.com> wrote:
> Tom,
>
> I did make some changes but that actually is still causing me to
> output each line while looping through the file instead of only adding
> unique key value pairs to the hash. I can only guess I am overriding
> the hash each time it loops? Also don't understand the line break I
> am getting between the number and is unique.
snip
Here is the output I get from your code:
The cellphone is unique
The cola is unique
The monitors is unique
The mugs is unique
Okay, I see 3 possibilities.
1. You are not running the code you think your are running
(unsaved file, saved to wrong file, etc)
2. There is something weird about your environment you haven't told us yet.
3. You copied the code by hand and fixed the bug in the transfer.
Also, here is a list of things you can do (or not do) to make your code better.
1. always use the strict pragma
2. always use the three argument version of open
3. use \n inside strings rather than counting on a literal linefeed working
4. numbering your errors in die is worthless, the file and line
number are printed automatically if the the error string does not end
with \n
5. only use parenthesis when you really need them, "my (%hash);" is foolish
6. learn when you need to specify the default variable ($_) and
when you don't
7. never use an if statement just to get the else clause, use
"unless (exists $hash{$product})", "if (not exists $hash{$product})",
or "if (!exists $hash{$product})"
Here is your code after following the advice above.
#!/usr/bin/perl
use strict;
use warnings;
my $infile = 'products.out';
open my $file, '<', $infile
or die "could not open $infile for reading:$!\nStopped";
my %hash;
while(<$file> ) {
my ($product, $qty) = split /\|/;
unless (exists $hash{$product}) {
$hash{$product} = $qty;
print "The $product is unique\n";
}
}
|
|
|
|
|