how to evaluate values in a hash

M

monte

i need to evalue hte values of a hash for a given key. I am new to perl
and I need a little help. I am doing a hash where the key is the cell
and the value is the lib but now that I got the values how to eval the
values and have them print only once in the output.
INPUT file format:
lib0 cell1
lib2 cell3
lib2 cell4
lib3 cell3
lib0 cell1
lib2 cell4
lib2 cell4
etc..

DESIRED ouput:
cell1 lib0 (lib0 should only appears once in output)
cell3 lib2 lib3 (this is an error)
cell4 lib2

MY code outputs:
cell1 lib0 lib0
cell3 lib2 lib3
cell4 lib2 lib2 lib2

my code is the following but I need help evaluating the values to check
that the current lib is the same as the previous lib and output the
name only once if it is the same lib otherwise return an error message.
can you please give a hint on how to do this values checking?

($rec{$cell}= "Cell:$cell Lib:") if (! exists($rec{$cell}));
$rec{$cell}.="$lib\t"; #this here produces my code output
foreach $cell(keys %rec)
{
print" $rec{$cell}\n";
}
 
X

xhoster

monte said:
i need to evalue hte values of a hash for a given key. I am new to perl
and I need a little help. I am doing a hash where the key is the cell
and the value is the lib but now that I got the values how to eval the
values and have them print only once in the output.
INPUT file format:
lib0 cell1
lib2 cell3
lib2 cell4
lib3 cell3
lib0 cell1
lib2 cell4
lib2 cell4
etc..

DESIRED ouput:
cell1 lib0 (lib0 should only appears once in output)
cell3 lib2 lib3 (this is an error)
cell4 lib2

Are the things in parentheis supposed to be part of the output
or not?

MY code outputs:
cell1 lib0 lib0
cell3 lib2 lib3
cell4 lib2 lib2 lib2

No, your code doesn't output that. Even after I fix it by adding
the missing loop and split, it still doesn't output that.

my code is the following but I need help evaluating the values to check
that the current lib is the same as the previous lib

You mean previous for the same cell? If each one must be the same
as the previous, then there are only ever allowed to be one lib per
cell, right?
and output the
name only once if it is the same lib otherwise return an error message.

What you mean by "return"? There doesn't seem to be any returnable blocks
here.
can you please give a hint on how to do this values checking?

You are missing something like:

($rec{$cell}= "Cell:$cell Lib:") if (! exists($rec{$cell}));
$rec{$cell}.="$lib\t"; #this here produces my code output

if (! exists $rec{$cell}) {
$rec{$cell}=$lib;
} else {
die "Error message" unless $rec{$cell} eq $lib;
};

};
foreach $cell(keys %rec)
{
print" $rec{$cell}\n";
}

Xho
 
M

monte

yes, Mahesh, I see what you're doing, sorry for not putting as much of
my code as possible, will do next time I ask a basic question to you. I
will make the libs to be a hash, too. I will keep you updated if i ran
into more trouble but for now, thanks for all of you guys help! I know
it is too late to post my code but here it is.


my code:
while(<>)
{
chomp;
$show_file=$_;
next if ( $show_file=~/\#/);
#print $show_file;
if ($show_file=~/^\S+\s+\d\.\s+(\S+)\s+(\S+)/) #this is the parsing
pice to get my cell and lib
{
$lib=$1 if defined ($1);
$cell=$2 if defined ($2);

#checking if the same cell exist in the same heirarchy.key=>cell,
value=>lib

($rec{$cell}= "Cell:$cell Lib:") if (! exists($rec{$cell}));
$rec{$cell}.="$lib\t";
}}
foreach $entry (keys %rec)
{
print" $rec{$entry}\n";
}
 
T

Tad McClellan

monte said:
sorry for not putting as much of
my code as possible, will do next time


Have you seen the Posting Guidelines that are posted here frequently?
 
F

Fabian Pilkowski

* monte said:
yes, Mahesh, I see what you're doing, sorry for not putting as much of
my code as possible, will do next time I ask a basic question to you. I
will make the libs to be a hash, too. I will keep you updated if i ran
into more trouble but for now, thanks for all of you guys help! I know
it is too late to post my code but here it is.

my code:
while(<>) {
chomp;

You don't need to chomp here. You're just matching against your string
without paying attention to any line endings.
$show_file=$_;
next if ( $show_file=~/\#/);

Do you really need a named var $show_file, just a copy of $_? Consider,
the m//-operator you're using here matchs against $_ per default. Btw,
there's no need to escape »#«. Hence you could simply write:

next if /#/;

#print $show_file;
if ($show_file=~/^\S+\s+\d\.\s+(\S+)\s+(\S+)/) #this is the parsing
pice to get my cell and lib

Delete the »$show_file=~« part in this line. Then you're matching
against $_ as described above. It's the same, but shorter ;-)
{
$lib=$1 if defined ($1);
$cell=$2 if defined ($2);

By enclosing your regex by an »if« you already guarantee that the regex
has matched. Furthermore the vars $1 and $2 are defined, surely. There's
no need to check this again. Btw, are you using »strict« and »warnings«?

my( $lib, $cell ) = ( $1, $2 );
#checking if the same cell exist in the same heirarchy.key=>cell,
value=>lib

($rec{$cell}= "Cell:$cell Lib:") if (! exists($rec{$cell}));

You could remove some parantheses to provide more readability.

$rec{$cell} = "Cell:$cell Lib:" if ! exists $rec{$cell};

Btw, you don't need to check if the key already exists(). You could use
the operator »||« (»or«) to assign a value if there isn't one.

$rec{$cell} = $rec{cell} || "Cell:$cell Lib:";

But, in Perl that's not short enough -- we could shorten to:

$rec{$cell} ||= "Cell:$cell Lib:";

$rec{$cell}.="$lib\t";
}}

Ok, the closing brackets for while loop and if condition. In one line.
Btw, your coding style isn't the best I ever read. Consider to indent
your lines to separate different blocks. Use more spaces and newlines
wherever you think they could improve the readability.

foreach $entry (keys %rec) {
print" $rec{$entry}\n";
}

You know about values() to get the values and not the keys?

print " $_\n" for values %rec;

regards,
fabian
 
J

John Bokma

Fabian said:
You could remove some parantheses to provide more readability.

$rec{$cell} = "Cell:$cell Lib:" if ! exists $rec{$cell};

$rec{$cell} = "Cell:$cell Lib:" unless exists $rec{$cell};

I love unless :)

or:

exists $rec{$cell} or $rec{$cell} = "Cell:$cell Lib:";

OTOH, just overwriting is also possible in this case.
Btw, you don't need to check if the key already exists(). You could
use the operator »||« (»or«) to assign a value if there isn't one.


$rec{$cell} = $rec{cell} || "Cell:$cell Lib:";

But, in Perl that's not short enough -- we could shorten to:

$rec{$cell} ||= "Cell:$cell Lib:";


There are cases that this use of "or" gives very unexpected results.
This is not such a case, but be aware, e.g.

$filename ||= 'default.txt';

now imagine $filename is 0, and 0 is a legal name...
 
M

monte

print "$cell (" . (join ", ", sort keys %{$rec->{$cell}}) . ")",
(keys %{$rec->{$cell}} > 1) ? " - Error?" : "",
I have been trying to understand the syntax of the statement such as
the column after error and the comma after the parenthesis. I have
looked for and instance like this on the book for the explanation but
can't see one, can you kindly explain the syntatically format of the
statement?
 
J

John Bokma

monte said:
print "$cell (" . (join ", ", sort keys %{$rec->{$cell}}) . ")",
(keys %{$rec->{$cell}} > 1) ? " - Error?" : "",


print "$cell (" . (

join ", ", sort keys %{$rec->{$cell}}
) .

")",

( keys %{$rec->{$cell}} > 1 ) ? " - Error?" : "",

Which is quite ugly written in the first place :-D.

print "$cel (",
join( ", ", sort keys %{ $rec->{$cell} } ),
")",
( keys %{$rec->{$cell}} > 1 ) ? " - Error?" : "",

with using a variable it can be made a bit more readable:

my @contents = sort keys %{ $rec->{ $cell } };

print "$cel (", join( ",", @contents), ")",
@contents > 1 ? " - Error?" : "",
 
T

Tad McClellan

[ snip several alternative codings ]

with using a variable it can be made a bit more readable:

my @contents = sort keys %{ $rec->{ $cell } };

print "$cel (", join( ",", @contents), ")",
@contents > 1 ? " - Error?" : "",


Once we resign to putting it into an array, this would be my
candidate for "easiest to read and understand":

{
my @contents = sort keys %{ $rec->{ $cell } };
local $" = ',';
print "$cel (@contents)";
print ' - Error?' if @contents > 1;
}
 
M

monte

you guys have been extremely helpful and I'd like so say THANK YOU :^)

Tad said:
[ snip several alternative codings ]

with using a variable it can be made a bit more readable:

my @contents = sort keys %{ $rec->{ $cell } };

print "$cel (", join( ",", @contents), ")",
@contents > 1 ? " - Error?" : "",


Once we resign to putting it into an array, this would be my
candidate for "easiest to read and understand":

{
my @contents = sort keys %{ $rec->{ $cell } };
local $" = ',';
print "$cel (@contents)";
print ' - Error?' if @contents > 1;
}
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,817
Latest member
DicWeils

Latest Threads

Top