Re: How to maintain hash relationship?

Re: How to maintain hash relationship?

am 19.12.2007 15:46:17 von bill

On Dec 17, 5:07 pm, Fred wrote:
> I'm not sure if I'm phrasing the question correctly, but here goes -- In
> ...

Fred,
I've modified your original code to do what it sounds like you want it
to do. You also mentioned returning a hash, so I included two ways of
doing that. Enter a city on the command line and look at the code
near
the end of the main() "section". You could also use a hash keyed on
the
city which pointed to an array of name records.
-Bill

#!/usr/local/bin/perl

use strict;
use warnings;

my %field_pos;
my %people;

%field_pos =
(
'FIRST_NAME', 0,
'LAST_NAME', 1,
'CITY', 2,
);

# Save where __DATA__ starts in our script
# so we can get back there for sub-sequent
# reads (this must occur prior to the first
# read from )
#
my $DATA_START_POS = tell(DATA);

# Altered original
#
while ( )
{
chomp;
s/\s$//;
my @data = split /\s*,\s*/;
my $key = "$data[1], $data[0]";
map { $people{$key}->{$_} = $data[$field_pos{$_}] } keys
%field_pos;
}

show_hash('people', \%people);

#-----------------------------

# Alternate version 1
#
my %people1 = get_data1();

show_hash('people1', \%people1);

#-----------------------------

# Alternate version 2
#
my %people2;
get_data2(\%people2);

show_hash('people2', \%people2);


# Show any people that live in the city entered on the command line
#
print "\n";
my $found = 0;
if ( $ARGV[0] )
{
foreach my $key ( sort keys %people )
{
my $rec = $people{$key};
next unless ( $ARGV[0] eq $rec->{CITY} );
print "$rec->{FIRST_NAME} $rec->{LAST_NAME} lives in
$ARGV[0]\n";
$found++;
}
}

printf "\n%s in $ARGV[0]\n", ( $found )
? sprintf "$found %s", ( $found == 1 ) ?
'person lives' : 'people live'
: "No one lives";

#END main()


sub get_data1
{
my %rethash;

# Rewind __DATA__ to its beginning
#
seek(DATA, $DATA_START_POS, 0);

while ( )
{
chomp;
s/\s$//;
my @data = split /\s*,\s*/;
my $key = "$data[0] $data[1]";
map { $rethash{$key}->{$_} = $data[$field_pos{$_}] } keys
%field_pos;
}
return(%rethash);
}


sub get_data2
{
my($hashref) = @_;

# Rewind __DATA__ to its beginning
#
seek(DATA, $DATA_START_POS, 0);

while ( )
{
chomp;
s/\s//g;
my @data = split /,/;
my $key = "$data[1]$data[0]";
map { $$hashref{$key}->{$_} = $data[$field_pos{$_}] } keys
%field_pos;
}
# Since $hashref is just the "address" of %people2, the
# assignments we made were directly to %people2 so there's
# nothing to return (although you could return something
# like the number of records read)
}

sub show_hash
{
my($title, $hashref) = @_;

print "\n'$title' hash:\n";
foreach my $key ( sort keys %$hashref )
{
my $rec = $$hashref{$key};
printf " %-20s: %-7s %-13s %s\n", $key, $rec->{FIRST_NAME},
$rec->{LAST_NAME}, $rec->{CITY};
}
}

__DATA__
Fred, Flintstone, Bedrock
Wilma, Flintstone, Bedrock
Barney, Rubble, Moonrock

Re: How to maintain hash relationship?

am 19.12.2007 17:44:00 von krahnj

Bill wrote:
>
> On Dec 17, 5:07 pm, Fred wrote:
> > I'm not sure if I'm phrasing the question correctly, but here goes -- In
> > ...
>
> Fred,
> I've modified your original code to do what it sounds like you want it
> to do. You also mentioned returning a hash, so I included two ways of
> doing that. Enter a city on the command line and look at the code
> near
> the end of the main() "section". You could also use a hash keyed on
> the
> city which pointed to an array of name records.

[ SNIP ]

> # Altered original
> #
> while ( )
> {
> chomp;
> s/\s$//;
> my @data = split /\s*,\s*/;
> my $key = "$data[1], $data[0]";
> map { $people{$key}->{$_} = $data[$field_pos{$_}] } keys
> %field_pos;

You shouldn't use map in void context:

$people{$key}->{$_} = $data[$field_pos{$_}] for keys %field_pos;

> }

[ SNIP ]

> printf "\n%s in $ARGV[0]\n", ( $found )
> ? sprintf "$found %s", ( $found == 1 ) ?
> 'person lives' : 'people live'
> : "No one lives";

No need to use printf and sprintf there:

print
"\n",
( "$found person", "$found people", 'No one' )[ $found <=> 1 ],
' live',
$found < 2 ? 's' : '',
" in $ARGV[0]";



John
--
use Perl;
program
fulfillment