in reply to 2 newby questions

In addition to the good replies above, this:

chomp(@words = <STDIN>); foreach $word (@words){ $count{$word}++ } # is better done like this: while( my $word = <STDIN> ){ chomp $word; $count{$word}++; }

As you can see, the second idiom doesn't require the @words array at all, since it reads and processes the data one line at a time. That doesn't matter much for small amounts of data, but for larger amounts the first method could run into memory constraints. It's best to use the second method by default unless you must use the first for some reason.

Aaron B.
Available for small or large Perl jobs; see my home node.

Replies are listed 'Best First'.
Re^2: 2 newby questions
by Socrates440 (Acolyte) on Jun 14, 2012 at 23:22 UTC
    Wow, I did not expect this much feedback. Thank you all. I took what you posted, what my book recommended, and some other bits and pieces of information and I tried to reconstruct the program in my own way as best I could. Any critiques would be helpful. Particularly, how I could condense the program into fewer lines. Thanks!
    #!/usr/bin/perl -w use strict; my ($counter, $words, %counter) ; print "This program records all of the words you type and counts how o +ften you type them.\nPlease type in a list of words. Type done when +you are finished.\n" ; chomp ($words = <STDIN>) ; while ($words ne "done") { chomp ($words = <STDIN>) ; if ($words eq "done") { last ; } $counter{$words}++ ; } foreach $words (keys%counter) { if ($counter{$words} <= 1) { print "You typed $words $counter{$words} time." } else { print "You typed $words $counter{$words} times." ; } }

      You're kind of repeating yourself inside and outside your while loop, so that can be condensed. Here's a more perlish way to do it. It confines the $word variable to the smallest possible scope, and uses a statement modifier after last to shorten things and make the logic clearer (in my opinion).

      while( my $word = <STDIN> ){ chomp $word; last if $word eq 'done'; $counter{$word}++; }

      On your foreach loop, you can eliminate the if/else with a ternary operator:

      for my $word (keys %counter){ print "You typed $word $counter{$word} time" .($counter{$word}>1 ? ' +s' : ''). ".\n"; # or printf "You typed %s %d time%s.\n", $word, $counter{$word}, ($counte +r{$word}>1?'s':''); }

      Aaron B.
      Available for small or large Perl jobs; see my home node.

      You can shorten your while loop:

      $counter{$_}++ while chomp($_ = <>) && !/^done$/i;

      I threw in !/^done$/i to terminate on "Done", "DONE", etc.

      And note the subtle suggestion of others to change $words to $word, which is clearer.

      What about this one, is this code condensed enough?

      #!/usr/bin/perl -w use strict; use warnings; my %counter; print "This program records all of the words you type and counts how oft +en you type them.\nPlease type in a list of words. Type done when yo +u are finished.\n"; $counter{$_}++ while chomp($_ = <STDIN>) && !/^done$/i; foreach my $line ( sort keys %counter ) { printf "You typed '$line' $counter{$line} time%s.\n", ($counter{$l +ine} == 1) ? "" : "s"; }

      Also note the 'my' in the foreach, always use this idiom!