A cleaner way to iterate in a python dictionary to avoid many nested loops

Is there a better way to repeat my vocabulary data without using 3 nested for loops , like what I'm doing right now, given the data below? Btw, I am using python 2.6.

 data = {'08132012': { 'id01': [{'code': '02343','status': 'P'},{'code': '03343','status': 'F'}], 'id02': [{'code': '18141','status': 'F'},{'code': '07777','status': 'F'}] } } 

Here is 3 for current current loop:

  for date in data: for id in data[date]: for trans in data[date][id]: print "Date: %s" % date print "Processing id: %s" % id print trans['code'] print trans['status'] //query to database 

EDITED : Valid Data Values

+7
source share
3 answers

Given the nested nature of the data, I don’t think that somewhere you can avoid some nested loops.

However, you can not embed most of your programming logic by creating a smoothing generator for your data, for example:

 def flatten(data): for date in data: for id in data[date]: for trans in data[date][id]: yield (date, id, trans) def process(data): for date, id, trans in flatten(data): # do stuff with date, id, trans 
+8
source

Without knowing more details about the origin of the data, the solution I would like to make is to consider using namedtuple if it is possible to change the data storage structure. This will make things cleaner and more readable.

Here is an example:

 >>> from collections import namedtuple >>> Record = namedtuple('Record', ['date', 'id', 'code', 'status']) >>> records = [] >>> records.append(Record('08132012', 'id01', '02343','P')) >>> records.append(Record('08132012', 'id01', '03343','F')) >>> records.append(Record('08132012', 'id02', '18131','F')) >>> records.append(Record('08132012', 'id02', '07777','F')) >>> for record in records: ... print "Date: %s" %record.date ... print "Processing id: %s" %record.id ... print record.code ... print record.status ... Date: 08132012 Processing id: id01 02343 P Date: 08132012 Processing id: id01 03343 F Date: 08132012 Processing id: id02 18131 F Date: 08132012 Processing id: id02 07777 F 

More fun:

Get a list of entries where status is 'F':

 >>> Fs = [record for record in records if record.status == 'F'] >>> Fs [Record(date='08132012', id='id01', code='03343', status='F'), Record(date='08132012', id='id02', code='18131', status='F'), Record(date='08132012', id='id02', code='07777', status='F')] 

Sort by code :

 >>> records.append(Record('08122012', 'id03', '00001', 'P')) >>> records.sort(key=lambda x:x.code) >>> records [Record(date='08122012', id='id03', code='00001', status='P'), Record(date='08132012', id='id01', code='02343', status='P'), Record(date='08132012', id='id01', code='03343', status='F'), Record(date='08132012', id='id02', code='07777', status='F'), Record(date='08132012', id='id02', code='18131', status='F')] 
+4
source

The generator is pretty simple:

 >>> flat = ((d, id, t) for d in data for id in data[d] for t in data[d][id]) >>> for date, id, trans in flat: ... print date, id, trans ... 08132012 id02 {'status': 'F', 'code': '18141'} 08132012 id02 {'status': 'F', 'code': '07777'} 08132012 id01 {'status': 'P', 'code': '02343'} 08132012 id01 {'status': 'F', 'code': '03343'} >>> 
+3
source

All Articles