4 ms·
> It's quite possible that a sorted word count was easiest to do with bash and unix utilities in 1992. Now, it's easier and more comprehensible in your favorit
by mschaef 8y ago
> It's quite possible that a sorted word count was easiest to do with bash and unix utilities in 1992. Now, it's easier and more comprehensible in your favorite scripting language
It'd be interesting to see how true this is in reality. I'm not at all convinced that most scripting languages can do this quite as concisely as bash and the Unix userland. (But, being honest, this problem seems very well aligned to that tooling's strenghts.)
- sobellian 8y agoWell, what is easy or comprehensible isn't necessarily concise. Bash is great for code golf but I know few people who prefer to code in it.
- sobellian 8y agoAnd for completeness, a Ruby implementation: puts STDIN.read .split(/[^A-Za-z]+/) .group_by(&:downcase).transform_values(&:size) .sort_by(&:last).reverse .take(ARGV[0].to_i) .map{ |l| l.join("\t") }.join("\n") Wordier than the bash script, but still pretty short and fairly trivial. Anyone could make this in five minutes.
- btilly 8y agoIt 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 })