3 ms·
It is easy to do in your favorite scripting language. But is unlikely to be as short. Comprehensibility is in the eye of the beholder. Here is a Perl solutio
by btilly 8y ago
It is easy to do in your favorite scripting language. But is unlikely to be as short. Comprehensibility is in the eye of the beholder.
Here is a Perl solution for comparison.
use strict;
use warnings;
my $limit = shift @ARGV;
my %count;
for my $line (<>) {
while ($line =~ /(\w+)/g) {
$count{lc $1}++;
}
}
@words = sort {$count{$b} <=> $count{$a} or $a cmp $b} keys %count;
$limit = @words if @words < $limit;
print "$_\t$count{$_}\n" for @words[0..($limit-1)];
- mkl 8y agoPython is relatively short, batteries included and all that: import re import sys import collections words = re.findall('[a-z]+', sys.stdin.read().lower()) c = collections.Counter(words) for word, count in c.most_common(int(sys.argv[1])): print(f'{count:>7} {word}') Three times the character count of the Unix pipe version, but IMHO a lot more readable (and generalisable).
- mkesper 8y agoYou don't want to read all input into memory first.
- mkl 8y agoFair enough. import re import sys import collections c = collections.Counter() for line in sys.stdin: words = re.findall('[a-z]+', line.lower()) c.update(words) for word, count in c.most_common(int(sys.argv[1])): print(f'{count:>7} {word}')
- lizmat 8y agoJust for reference: a Perl 6 version: sub MAIN($limit = Inf) { my %bag is Bag = words.map(&lc); say "{.key}\t{.value}" for %bag.sort( { $^b.value cmp $^a.value || $^a.key cmp $^b.key } )[^$limit] } And for what it's worth, the `words` function is lazy, so it won't read all of the words into memory first.
- b2gills 8y agoI would have written the sort differently %bag.sort({ -.value, .key })