Eyes, please uncross thyselves

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
Comments have been closed on this topic.