If you want to count the occurrence of each item independantly, and you want to strip the first line off as a header line, and you want the list of items that you're counting to be easily adjustable, this will do the trick.

my $header_line = <DATA>; my %count; my @chars = ( qw/F G S/ ); while (my $line = <DATA> ) { eval "\$count{$_} += \$line =~ tr/$_/$_/,1" or die $@ foreach @chars; } print "There are $count{$_} occurrences of $_\n" foreach sort keys %count; __DATA__ Sample header hine FDIELSIGCOXLSAGICK\n FDIELSIGCOXLSAGICK\n

The reason that the tr/// must appear inside of an eval block is that variables are not interpolated in tr/// (the transliteration table is built at compiletime, not runtime). Eval forces a fresh compilation of tr/// each time through the loop.

The reason that I pass references is because I want the variables to exist as variables inside the eval, not as values (except in the case of what's inside the tr/// itself).

And the '1' appears at the end of the eval expression so that eval returns safely (without croaking) even if no matches are found.

I think this is an elegant solution, and saves a lot of intricate fiddling.

If you want to see a solution that uses index instead of tr///, you may...


Just to see what it would look like I also did it with index instead of a regexp or tr/// counting mechanism. The index method took three loops, and I don't really like it that much, but it works, and has the advantage of also working if you are looking for whole words instead of just individual letters. Here it is.

use strict; use warnings; my $header_line = <DATA>; my %count; my @chars = ( qw/F G S/ ); while ( my $line = <DATA> ) { foreach ( @chars ) { my $pos = 0; while ( ($pos = index( $line, $_, $pos ) ) >= 0) { $count{$_}++; $pos++; } } } print "There are $count{$_} occurrences of $_\n" foreach sort keys %count; __DATA__ Sample header hine FDIELSIGCOXLSAGICK\n FDIELSIGCOXLSAGICK\n

I still prefer the flow of the tr/// or m//g methods, but index definately gets the job done without mucking things up too badly.

Dave

"If I had my life to do over again, I'd be a plumber." -- Albert Einstein


In reply to Re: Re: Re: counting occurances by davido
in thread counting occurances by imlou

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.