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.
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?)