Ugh. I missed out on my rant yesterday as I was feeling sorry for myself. I was banging my head against three languages I've always wanted more time to play with. (So, I guess I shouldn't have banged my head, but I should be happy)
For reasons that I won't get into right now, I'll show you the code I was working on. Feel free to (gently) correct me if I've gotten anything majorly wrong. The following three blocks all do the same thing, process an XML file that contains (among other elements) city names. The code returns the count of each city. I've included them in the order I wrote them, so you can see similarities and/or growth:
Ruby
First one in, and the one I had least problem with. In fact, I think the only thing that bunged me up a little was the dump_list at the end. Anonymous methods/closures/blocks blow my mind. Kind of like recursion; sometimes a bit much for this non-CompSci brain.
require 'rexml/document'
require 'rexml/streamlistener'
include REXML
include Parsers
class Listener
include StreamListener
def initialize
@cities = Hash.new(0)
@flag = false
end
def tag_start(name, attributes)
if name == 'city'
@flag = true
end
end
def tag_end(name)
if name == 'customers' #end of document
puts
dump_list
end
end
def text(text)
if @flag
puts "Adding " +text
@cities[text] = @cities[text] + 1
@flag = false
end
end
def dump_list()
puts ">> Count of each city"
@cities.each {|key, value| puts key+ ": " +value.to_s }
puts "==="
end
end
listener = Listener.new
parser = StreamParser.new(File.new("customers.xml"), listener)
parser.parse
Perl
Triple Ugh. People do this by choice? (OK, put away the flamethrowers)
use XML::Parser;
my $file = 'customers.xml';
my $parser = new XML::Parser();
my %cities;
my $flag = 0;
sub start_handler {
my $p = shift;
my $elem = shift;
if ($elem =~ /city/) {
$flag = 1;
}
}sub end_handler {
my $p = shift;
my $elem = shift;
if ($elem =~ /customers/) {
foreach $city (keys %{$cities}) {
print $city, ": ", %{$cities}->{$city}, "\n";
}
}
}
sub char_handler {
if($flag) {
my ($p, $data) = @_;
$cities->{$data}++;
$flag = 0;
}
}$parser->setHandlers(Start => \&start_handler,
End => \&end_handler,
Char => \&char_handler);
$parser->parsefile($file);
Python
A bit of grief around that hash dictionary, including a less than decent error message on my first implementation of the increment.
from xml.sax import make_parser
from xml.sax import saxutils
file = "customers.xml"
class CityCounter(saxutils.DefaultHandler):
def __init__(self):
self.in_city = 0
self.cities = {}
def startElement(self, name, attrs):
if name == 'city':
self.in_city = 1
def endElement(self, name):
if name == 'customers':
for city, count in self.cities.items():
print city, ": ", count
def characters(self, text):
if self.in_city:
self.in_city = 0
if self.cities.has_key(text):
self.cities[text] = self.cities[text] + 1
else:
self.cities[text] = 1
#main routine
p = make_parser()
cc = CityCounter()
p.setContentHandler(cc)
p.parse(file)
Print | posted on Thursday, November 24, 2005 5:44 AM