rchou2 has asked for the wisdom of the Perl Monks concerning the following question:
I currently have a file named file.200207 with data such as john 2 4
chris 3 5
lisa 1 3
I am trying to search the files from the 3 previous months, file.200204, file.200205, file.200206 and keep a count on the total number of times each name in file.200207 shows up in the three files from the last three months...any suggestions?
break up the problem
by cebrown (Pilgrim) on Jul 24, 2002 at 19:21 UTC
|
Hi -- in the interest of helping you help yourself I would suggest you break up the problem into subproblems.
- Read in this month's file and use the split function to find the first word on each line, then update a hash, using that first word as the key.
- Determine the name of the file for each of the previous three months (sort of tricky -- think about in February 2003 -- you need to get 200211, 200212, and 200301).
- For each of those files:
- create a new hash, let's call it the "counter" hash
- read in each record and split to find the first word.
- if the word is in the "this month" hash, increment your counter hash.
- when you're done reading a given file, print out the counter hash.
Each of these subproblems is pretty simple on its own, so start there and report back if you're struggling. | [reply] |
|
cebrown,
I tried doing this......
I already created a hash dataname with the names......
foreach $Name (sort keys %dataname)
{
for (APRIL, MAY, JUNE) {
if ($count{$Name}) {
$count{$Name}++;
}
}
printf OUTFILE "%-50s %d\n", $Name, $count{$Interface_Name};
but it just seems to be adding 1 count after each loop...any suggestions? | [reply] [d/l] |
|
Are you sure your code is doing what you think it's doing? When I read it, it's saying
- For every name in this list, do the following:
- If I have a non-zero number in the location $count{$Name}, then I need to add 1 to the location specified by $count{Name}
- Print stuff out to somewhere.
That doesn't seem like that's what you want to do. In fact, it's doing exactly what you're complaining it's doing. :-)
------ We are the carpenters and bricklayers of the Information Age. Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.
| [reply] [d/l] [select] |
|
Well, "APRIL, MAY, JUNE" is just a list of three strings. Perl is iterating across each element in that list and doing the stuff inside the for loop exactly three times, once for each string.
Elsewhere in the program I assume you did something like open APRIL, "<200204";. If that's the case, you need to use the special angle bracket operator to iterate through each record in a file, like while(<APRIL>) {do stuff}. Note also that while you are looping through each file you still need to perform the split on each record in order to find the name that's on a given record.
| [reply] [d/l] [select] |
|
Re: Searching Files
by fuzzyping (Chaplain) on Jul 24, 2002 at 19:29 UTC
|
Increment a hash value for each hash key (where the key is your date or filename in a HoH). Note that the use of Data::Dumper is just to show you the structure of the Hash of Hashes. It's up to you to figure out what to do with the data.
-fp
#!/usr/bin/perl
use Data::Dumper;
use strict;
my %count;
for my $i (3..6) {
my $filename = "file.20020$i";
open(DATA,$filename);
while (<DATA>) {
my ($name) = split(/\s+/,$_);
$count{$filename}{$name}++;
}
}
print Dumper %count;
------------------------------------------------------------
Prints:
$VAR1 = 'file.200206';
$VAR2 = {
'john' => '1',
'chris' => '1',
'lisa' => '1'
};
Update: Note about Data::Dumper, and removed parantheses from around split(). | [reply] [d/l] [select] |
Re: Searching Files
by dimmesdale (Friar) on Jul 24, 2002 at 19:14 UTC
|
open(FH,'file.200207') or die 'hlpfl err msg';
while(<FH>) {
# get name
$name = (split /\s+/, $_)[0];
# init count
$info->{$name} = 0;
}
for('file.200204','file.200205','file.200206') {
open(FH, $_) or die 'nther hlpfl err msg';
while(<FH>) {
# get name
$name = (split /\s+/, $_)[0];
# update count
if(defined $info->{$name}) { $info->{$name}++ }
}
}
Just a suggestion. Haven't tested it, so use with caution.
update: Hmm... I see fuzzyping has posted a very valid solution to your problem too ... only he keeps track of the name appearing in individual files, and I keep the entire sum. I didn't even think about that-- I don't know what you meant in your original post (it looks like it could go either way from re-reading it), but there's yet another disclaimer :)
| [reply] [d/l] |
Re: Searching Files
by PhiRatE (Monk) on Jul 24, 2002 at 22:31 UTC
|
Other people have already posted reasonable solutions so I'll concentrate on the meta-problem here.
You keep posting questions like this, "I have file of format x with data y and I need to sort/count/total/modify it in way z". I think what you really need to do is likely to involve getting a book on SQL and installing a database. All these problems could have been solved in much more effective ways using simple SQL statements.
In this particular instance, what the poor monks responding to your question took 10+ lines to do could be done in one:
select n2.name,count(*) from datastore as n1, datastore as n2 where n2
+.name=n1.name and n2.yearmonth=200207 and n1.yearmonth<200207 group b
+y n2.name;
Databases really come into their own with tabular data like this and if you're working with it a lot I *highly* recommend getting the necessary books, reading the online tutorials and installing one of the freely available RDBMSs (MySQL, PostGreSQL). That way the only thing you'll have to get perl to do is load the data in, from there you can play to your hearts content.
| [reply] [d/l] |
|
|