Sunday, September 23, 2007

Zen Python: The Sound of One Record Appending

Recently, I tried to make a Python program ultra-terse, as a fun puzzle.

I re-discovered two things:
  • I love Python. I hadn't used it in years and yet I was "back in gear" within a few minutes.
  • Python just seems to work. It is like a substance that can be a solid or a liquid, depending on your requirements, and at the same time.
In particular, I found that Python V 2.5 has some pretty cool ways of handling empty maps, or 'dictionaries' (in the Python parlance). This is elegant stuff, and yet easy enough that you need not know Python.

Consider a problem where we want to organize participants in a triathlon: a person has a name, gender, and age. Age groups will be 20s, 30s, 40s, etc.

By using a lambda expression (think anonymous function), on a defaultdict method, we can specify the default behaviour of a dictionary when there is no entry for the key.

myEasyMap = collections.defaultdict (lambda:[])

In this case, myEasyMap will create an empty list and insert it, when a key is not found. For example:

myEasyMap = collections.defaultdict (lambda:[])
myEasyMap[30].append("John Smith")

The above example appends "John Smith" into the list of triathletes in the 30s, even though there were not yet any listed.

The really cool thing is that we can chain these default dictionaries:

myData = collections.defaultdict (lambda: collections.defaultdict (lambda:[]))

myData["M"][30].append("John Smith")
myData["F"][20].append("Barbara Doe")

Above, myData is a map that resolves to a map of lists. There are two outer keys ("M" and "F"); the inner keys are the age ranges.

Should we do this in production? Probably not. But it is gorgeous.

Below, we iterate over some records and organize athletes:

myData = collections.defaultdict (lambda: collections.defaultdict (lambda:[]))

records = []
records.append( { 'name': "John Smith", 'age': 35, 'gender': "M" } )
records.append( { 'name': "Axl Rose", 'age': 45, 'gender': "M" } )
records.append( { 'name': "Britney Doe", 'age': 25, 'gender': "F" } )

for record in records:
name = record['name']
age = record['age'] % 10
gender = record['gender']
myData[ gender ][ age ].append( name )

Neato with a capital 'O'.

Ruby has similar behaviour, which is not surprising (see Porsches and Ferraris) but I don't know many languages that can do this. (e.g. I don't know of a way to do it in Groovy. Do you, Groovy readers?)

1 comment:

  1. So to have a good attack, you should level your skill in cabal online alz. Also, get the highest level jewelry that you can equip in thecabal alz. This step depends on your skill rank, for lower magic ranks get 4 fast notice arrow skills and your cabal gold. Of course, if you have more cabal money, you can get more in the game. By the way, you can buy pet from other players in buy cabal alz.
    Many people play the game maybe feel that they were too poor, some of my friend often ask, why you play games so there is ghost gen.
    Say good pull so much I do not pull hedge with the US to talk about the game experience to make ghost online gen. I want to see if there is nothing worth ghost gold things and a very low price. The most important thing is you have ghost online gold. Also we have a good time happy in the game and hope earned more ghost money in the game.

    ReplyDelete