Trying to get Understanding on filehandle and split function in Perl
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Now what I have to do is modify this code to allow me to search by a name and I'm not quite understanding on how the names are stored in the hashes.
Now this is where I'm not quite understanding on line 4,5,and 6.
PHP Code:
open(PH, "customers.txt") or die "Cannot open customers.txt: $!\n"; while(<PH>) { chomp; ($number, $email) = (split(/s+/, $_))[1,2]; $Phone{$number}=$_; $Email{$email}=$_; } close(PH);
Now from what I understand
line 1: open customers.txt for reading
line 2: begins the loop untill it run out of lines in customers.txt
line3: removes all the new lines off of each line
line 4: take something like
($number, $email) = (split(/s+/, $_))[1,2];
now from what I understand the split is splitting on pattern whie spaces to the end of line and [1,2] Is 1 for the number and 2 for the email. So does that mean 0 would be for name?
Really I just need a better explaination on how line 2-6 work out so I can modify the code to search by name.
Close. Firstly you need /\s+/ to split on spaces - currently you are splitting in literal 's'. Secondly, arrays are indexed from zero so you need [0,1,2] ... but since this is the entire array you don't in fact need to take a slice.
Code:
($name, $number, $email) = (split(/\s+/, $_));
Now, you can't use name as a hash key because name might not be unique (and isn't unique in the sample data!). This means that your new code will fail on 'Smith,John'.
So you need something like
Code:
$Names{$number} = $name;
in your file-read loop, and
Code:
if ($name) {
my $found = 0;
while (my ($tryphone, $tryname) = each(%Names)) {
if ($name eq $tryname) {
print "Customer: $Phone{$tryphone}\n";
$found = 1;
}
}
next if $found;
}
The original code uses email and phone as keys for two different hashes. I would say this is bad because you could have two customers with the same phone number (different people in the same building). Anyway it makes more sense to have a single hash for a single object - but you'd need to get to grips with hashes of hashes.
Last edited by SecretCode; 11-12-2011 at 06:24 AM.
So I know longer needed the whitespaces in front of each line in customers.txt. But I will try the while loop to search like you showed. I do see your point where I don't need the [0,1,2] since I'm returning the whole thing into a hash.
You really need to use one hash to contain all the elements of a customer's record.
And then build an array of hashes like this :
Code:
#!/usr/bin/perl
use warnings;
use strict;
my @CustomerRecords;
open(PH, "customers.txt") or die "Cannot open customers.txt: $!\n";
while(<PH>) {
chomp;
my %CustomerRecord;
($name, $number, $email) = (split(/s+/, $_));
## TODO: split $name on the ',' character and re-order it
## before assigning to the 'Name' element of the temporary hash
$CustomerRecord{'Name'} = $name;
$CustomerRecord{'Number'} = $number;
$CustomerRecord{'Email'} = $email;
push @CustomerRecords, { %CustomerRecord };
}
close(PH);
At this point, $CustomerRecords[0]{'Name'} will contain the first John Smith and $CustomerRecords[6]{'Name'}
the second occurrence of John Smith.
Each element of your final array will be a hash (aka an associative array) containing one person's details.
Then rework the remainder of your code to use these data structures.
you are losing hashes if you don't create a new hash for every record! Otherwise you will always use the same hash and push the same hash with new data onto the array which results in an array with all entries the same.
The normal way to use an array of hashes in perl is to use references to hashes. This means you create a new hash for every record and push a reference to the new hash onto the array.
Okay I see what your saying. I'm actually rewriting this code now but the keys is overwriting so technically I am losing hashes.
You're not 'losing' the hash, you are overwriting it.
The code I gave earlier declares a new hash for each record, from within the file reading loop. After all, you've one record per line and you need a hash for each record, yes? Plus you then need to push the hash
Code:
push @CustomerRecords, { %CustomerRecord };
, or its reference,
Code:
push @CustomerRecords, \%CustomerRecord ;
on to the array.
You could just use a reference within the loop,
Code:
while(<PH>) {
chomp;
my $CustomerRecord;
($name, $number, $email) = split;
## TODO: split $name on the ',' character and re-order it
## before assigning to the 'Name' element of the temporary hash
$CustomerRecord->{'Name'} = $name;
$CustomerRecord->{'Number'} = $number;
$CustomerRecord->{'Email'} = $email;
push @CustomerRecords, { $CustomerRecord };
}
But your accessors will change to
Code:
$CustomerRecords[0]->{'Name'}
If you encapsulate this effort into a subroutine and return a reference to the array you have generated, now containing a list of hashes. then the accessor will change to
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.