in reply to Re: tr/// statement
in thread tr/// statement

Could you please give me some more help on this tr/// statement?
Could you please tell me if there is any improvement I should do? I use something like this:
@letter = qw( a b c w x y ); for ($n=0; $n<6; $n++){ $x = $letter[$n]; $m = 0; open (DATA, "data.txt") || die "Could not open source data file."; while (<DATA>) { $cnt = eval "tr/$x/$x/"; $m += $cnt; } print "$x $m"; }
data.txt contains lines like:
aedj dfas jijiojsdf dsfwfy jiox jiohjdfax jojojdjj, oiiia oioje asfdc oujsdfayx soujfosdxjpoiojfdxjljojaois jojojx jopjpx jojoijx joijiodfx

asdfasdf jjalsdf jlajkldf jojiojsd jiojasj ioj wwdn jojae jojocjoc joijss jiojwx jiojoxuiojy joiyu oiuouyy

Replies are listed 'Best First'.
Re: A another tr/// statement question..
by kevin_i_orourke (Friar) on Jul 19, 2001 at 16:29 UTC

    This is unrelated to your tr/// problem but I would suggest using:

    foreach $x (@letter) {

    instead of your for loop, that way you don't have to remember to change the loop termination value from 6 if you change the number of letters.

    Kevin O'Rourke

      Muchas gracias Kevin!
Re: A another tr/// statement question..
by bwana147 (Pilgrim) on Jul 19, 2001 at 16:55 UTC

    I'd rather not open and close the file more than once: disk accesses take time (there's the cache, you didn't mention your file's size). Instead, I would first generate subs that count a given character and store them in a hash, referenced by that character.

    Then, for each line in the file, loop over the letters and call the sub from the hash. Increment a counter which is itself stored in a hash.

    #!/usr/local/bin/perl use strict; my @letter = qw/ a b c x y z /; my %subs; my %counts; foreach ( @letter ) { $subs{$_} = eval "sub { \$_[0] =~ tr/$_// }"; } while ( <DATA> ) { foreach my $letter ( @letter ) { $counts{$letter} += $subs{$letter}->($_); } } print "$_: $counts{$_}\n" foreach @letter; __DATA__ aedj dfas jijiojsdf dsfwfy jiox jiohjdfax jojojdjj, oiiia oioje asfdc +oujsdfayx soujfosdxjpoiojfdxjljojaois jojojx jopjpx jojoijx joijiodfx asdfasdf jjalsdf jlajkldf jojiojsd jiojasj ioj wwdn jojae jojocjoc joi +jss jiojwx jiojoxuiojy joiyu oiuouyy

    --bwana147

Re: A another tr/// statement question..
by stefan k (Curate) on Jul 19, 2001 at 16:34 UTC
    Hi,
    I'd write the whole thing as:
    @letter = qw/a b c w x y/; foreach $x (@letter) { $m = 0; open(DATA,"data.txt") or die "couldn't open data\n$!"; while (<DATA>) { $m += ($_ =~ s/$x/$x/g); } close(DATA); print "count $x = $m\n"; }
    (note the use of foreach, or and $! ...)

    Regards... Stefan

      Thank you very much Stefan!
Re: A another tr/// statement question..
by runrig (Abbot) on Jul 19, 2001 at 18:46 UTC
    If you just want letter counts, you could do something like this (though I have a hard time believing this is not homework):
    my $letters = "abcwxy"; my $re = qr/[$letters]/; my $cnt; while (<INPUT>) $cnt++ while /$re/g; } print "$cnt\n";