•
•
•
•
What is DaniWeb IT Discussion Community?
You're currently browsing the Perl section within the Software Development category of DaniWeb, a massive community of 374,176 software developers, web developers, Internet marketers, and tech gurus who are all enthusiastic about making contacts, networking, and learning from each other. In fact, there are 3,458 IT professionals currently interacting right now! Registration is free, only takes a minute and lets you enjoy all of the interactive features of the site.
Please support our Perl advertiser:
Views: 3217 | Replies: 32
![]() |
•
•
•
•
...
This is also not correct syntax:
elsif ($line[0] =! /=/)
should be:
elsif ($line[0] !~ /=/)
Thanks Kavin...
challenge the limits
Borrowing from katharnakh's code I corrected a couple of things and expanded on the processing.
use strict;
use warnings;
open(IN, "readme.txt") || die "ERROR: $!";
open(OUT, ">seeme.txt") || die "ERROR: $!";
my (%cnter, $marker);
while(<IN>) {
chomp;
my @line = split(/\s+/);
if($line[0] =~ /^=/) {
$line[0] =~ tr/=//d; # remove all the "=" from the section title
$marker = join(' ',@line); # rejoin the section title into a string
}
else {
tr/,.?!//d for @line; #remove some punctuation
tr/A-Z/a-z/ for @line; #convert all text to lower case so 'Word' and 'word' are the same
$cnter{$marker}{$_}++ for @line;
}
}
# sort words by count in descending order
foreach my $section (keys %cnter){
print OUT "$section\n";
foreach my $word (sort { $cnter{$section}{$b} <=> $cnter{$section}{$a} } keys %{$cnter{$section}}){
print OUT "$word: $cnter{$section}{$word}\n";
}
}
close(IN);
close(OUT); Last edited by KevinADC : Apr 9th, 2008 at 3:43 am.
Thank you. I updated my script and the output looks good. I did start using the 'warnings' and 'strict' commands as suggested to me in another thread. When I run the updated script I receive an 'unitialized value in pattern match' error for this line:
My output is correct, just not sure why I continue to receive this error. I tried to correct by updating it to read.
Didn't work. Also tried to add @line (as well as $line) to the line where 'my' variables are defined but no luck. Is this an error I would receive but could ignore? Thanks again for helping me understand.
if($line[0] =~ /^=/) {My output is correct, just not sure why I continue to receive this error. I tried to correct by updating it to read.
if(my $line[0] =~ /^=/) {Didn't work. Also tried to add @line (as well as $line) to the line where 'my' variables are defined but no luck. Is this an error I would receive but could ignore? Thanks again for helping me understand.
it's probably being caused by a blank line in the file. It is also a warning, not an error. Errors terminate scripts, warnings alert you to possible problems but the script keeps running.
You may want to try and skip blank lines in the file:
You may want to try and skip blank lines in the file:
while(<IN>) {
next if (/^\s*$/;
chomp; I didn't realize the blank lines would create warnings. No more warnings now. In reviewing the script, it looks like a hash of hashes were made. I added (after the 'while' section' and before the '#sort..':
I wanted to see what the values in each hash were (wanted understand the logic behind each portion). My output looked something like this:
Retirement Plan Fundamentals Part I => HASH(0x18f0554)
Retirement Plan Fundamentals Part III => HASH(0x1876a74)
.....
I am looking to compare the words from each section in an easier way to review. For example, output would like more like:
word/section Plan Part I : Plan Part II : Plan Part III
plans: 1 : 0 : 1
course: 0 : 1 : 1
.....
I know (keys %cnter) is the title part.
(keys %{cnter{$section}}) is each word in the title hash. Not sure where to start. If I do this:
I am only comparing the words in the section. I believe I need to assign each section a unique hash name so that it would look something like this:
I would use one of the sections as the base list so that when I compare other sections, I would just add a word if it's not there already.
Also, please let me know if I should start another thread. I want to make sure I follow proper form here.
Thanks-
my ($key, $value);
while (($key, $value) = each %cnter) {
print FILEOUT "$key => $value\n";
}I wanted to see what the values in each hash were (wanted understand the logic behind each portion). My output looked something like this:
Retirement Plan Fundamentals Part I => HASH(0x18f0554)
Retirement Plan Fundamentals Part III => HASH(0x1876a74)
.....
I am looking to compare the words from each section in an easier way to review. For example, output would like more like:
word/section Plan Part I : Plan Part II : Plan Part III
plans: 1 : 0 : 1
course: 0 : 1 : 1
.....
I know (keys %cnter) is the title part.
(keys %{cnter{$section}}) is each word in the title hash. Not sure where to start. If I do this:
(keys %{cnter{$section}}) eq (keys %{cnter{$section}})I am only comparing the words in the section. I believe I need to assign each section a unique hash name so that it would look something like this:
(keys %{cnter1{$section}}) eq (keys %{cnter2{$section}})I would use one of the sections as the base list so that when I compare other sections, I would just add a word if it's not there already.
Also, please let me know if I should start another thread. I want to make sure I follow proper form here.
Thanks-
Last edited by godevars : Apr 10th, 2008 at 5:55 pm.
•
•
•
•
...
I know (keys %cnter) is the title part.
(keys %{cnter{$section}}) is each word in the title hash. Not sure where to start. If I do this:
(keys %{cnter{$section}}) eq (keys %{cnter{$section}})
I am only comparing the words in the section. I believe I need to assign each section a unique hash name so that it would look something like this:
...(keys %{cnter1{$section}}) eq (keys %{cnter2{$section}})
Hi,
Its a good idea to have two or three sections, if you have two or three sections only(not more than that). But if sections in the input file is more than 3(may be 5 or 10) then having unique hash for each sections is not a good idea. So we can change a little bit in the way data is stored in the hash, so that it is easy to handle.
Now the data is stored in the hash is like this,
cnter{
section1 => {
word1 => count1,
word2 => count2
},
section2 => {
word1 => count1,
word2 => count2
},
...
}we will alter above hash, so that we will have one hash for entire section,
cnter{
word1 => [sec1_count, sec2_count, sec3_count....],
word2 => [sec1_count, sec2_count, sec3_count....],
...
}Note: Each index in the array is dedicated to perticular section, so word count should be incremented accordingly.
katharnakh.
Last edited by katharnakh : Apr 11th, 2008 at 12:28 am.
challenge the limits
I think the approach for the main data structure will have to be:
plus have a seperate array that holds the names of each section in the order it was found in the file.
word => {
section_titte => count
section_title => count
}
word => {
section_titte => count
section_title => count
}plus have a seperate array that holds the names of each section in the order it was found in the file.
A basic script, the output foramt is not real good but that will be up to you to change to your needs:
This does not allow for a lot of data analysis in and of itself. It simply lists the data by word and its count per section. If you wanted to sort by highest word frequency per section (for example) you would need to build a more robust data structure or open the file this script creates and parse that file with another script. You could look at the output of the above script as your basic statistics from which you could perform more analysis of the data.
use strict;
use warnings;
open(IN, "readme.txt") or die "ERROR: $!";
open(OUT, ">seeme.txt") or die "ERROR: $!";
my (%cnter, $title, @order);
while(<IN>) {
next if (/^\s*$/);
chomp;
my @line = split(/\s+/);
if($line[0] =~ /^=/) {
$line[0] =~ tr/=//d; # remove all the "=" from the section title
$title = "@line";
push @order, $title;
}
else {
tr/,.?!//d for @line; #remove some punctuation
tr/A-Z/a-z/ for @line; #convert all text to lower case so 'Word' and 'word' are the same
$cnter{$_}{$title}++ for @line;
}
}
print OUT join("\t",@order),"\n";
foreach my $word (sort keys %cnter){
print OUT "$word : ";
my @t = ();
foreach my $title (@order) {
push @t, (exists $cnter{$word}{$title}) ? $cnter{$word}{$title} : 0;
}
print OUT join("\t", @t),"\n";
}
close(IN);
close(OUT);This does not allow for a lot of data analysis in and of itself. It simply lists the data by word and its count per section. If you wanted to sort by highest word frequency per section (for example) you would need to build a more robust data structure or open the file this script creates and parse that file with another script. You could look at the output of the above script as your basic statistics from which you could perform more analysis of the data.
Last edited by KevinADC : Apr 11th, 2008 at 3:36 am.
•
•
•
•
It seems that the array approach would require you know all the sections beforehand.
It may require more than one process to get the final output. First build the hash that counts the words per section, then have another routine that builds the hash of arrays then prints the final output.
Here is the implementation according to the datastructure which i had mentioned earlier. Below code modifies Kavin's earlier posted code, just to show how the implementation goes. I have commented some lines just to compare two datastructure creation and manipulation
Perl Syntax (Toggle Plain Text)
use strict; use warnings; open(IN, "readme.txt") or die "ERROR: $!"; open(OUT, ">seeme.txt") or die "ERROR: $!"; my (%cnter, $title, @order); while(<IN>) { next if (/^\s*$/); chomp; my @line = split(/\s+/); if($line[0] =~ /^=/) { $line[0] =~ tr/=//d; # remove all the "=" from the section title $title = "@line"; push @order, $title; } else { tr/,.?!//d for @line; #remove some punctuation tr/A-Z/a-z/ for @line; #convert all text to lower case so 'Word' and 'word' are the same # a local hash to store { section => its index in the array my %index; @index{@order} = (0..$#order); #$cnter{$_}{$title}++ for @line; ${$cnter{$_}}[$index{$title}]++ for @line; } } print OUT join("\t",@order),"\n"; foreach my $word (sort keys %cnter){ print OUT "$word :"; my @t = (); my $index=0; foreach my $title (@order) { #push @t, (exists $cnter{$word}{$title}) ? $cnter{$word}{$title} : 0; push @t, (exists ${$cnter{$word}}[$index]) ? ${$cnter{$word}}[$index] : 0; } print OUT join("\t", @t),"\n"; } close(IN); close(OUT);
I appreciate Kavin's approach which is more simple, clean and code is more readable.
katharnakh.
Last edited by katharnakh : Apr 11th, 2008 at 7:18 am.
challenge the limits
![]() |
•
•
•
•
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
•
•
•
•
•
•
•
•
DaniWeb Perl Marketplace
Similar Threads
- Count characters of a string. (C++)
- Counting all Non-blank Characters in a String (Java)
- why does my string array do this? (C++)
- Counting specific characters in a string (C)
- Character/letter count (Pascal and Delphi)
- C++ BASICS ==> Pointers, Call by Reference/Value, Inheritance, Functions & Arrays (C++)
- String operatios (C++)
Other Threads in the Perl Forum
- Previous Thread: add text in the c functions.plz help me
- Next Thread: Can Array Name have Variable?


Linear Mode