### Exercise 6.7 ### Make a nested dictionary from a file ### OCL # First read the file into a list, with each list # element being a whole line in the file infile = open('human_evolution.txt', 'r') lines = infile.readlines() infile.close() # To be able to split each line into individual columns, # we first determine from the file header where (i.e. in # what position) each column starts and stops. The start # points are given by (a) 0 (the first column), (b) the # position where "(mill. yrs)" starts (the second column), # etc. The stop positions can easily be found from the # start positions; for example, the first column stops # right before the start of the second column. We assume # that the last column stops at position 80. s = lines[1] start = [0, s.index('(mill. yrs)'), s.index('height (m)'), s.index('mass (kg)'), s.index('(cm**3)')] stop = start[1:len(start)] + [80] # We also need to determine what is the first and last line # of data, since the file also contains some files with other # content. We notice that the data start with a line "---..." # and stop with a similar line. k = 0 while lines[k][0] != '-': k = k + 1 first = k + 1 k = first while lines[k][0] != '-': k = k + 1 last = k - 1 # We create an empty dictionary 'humans' and then go # sequentially through each line of data, extract each # of the columns and put into variables species, period, ... # We then create a "mini-dictionary" representing all # the data in a single line, and insert it into the larger # dictionary 'humans'. humans = {} for i in range(first, last+1): species = lines[i][start[0]:stop[0]].strip() period = lines[i][start[1]:stop[1]].strip() height = lines[i][start[2]:stop[2]].strip() weight = lines[i][start[3]:stop[3]].strip() volume = lines[i][start[4]:stop[4]].strip() humans[species] = {'period': period, 'height': height, 'weight': weight, 'volume': volume} # Finally, we print the contents of the dictionary 'humans' # as a nicely formatted table on the screen. The exact width # of each column was determined by a little bit of trial and # error. # First the header s = '%-23s %-13s %-13s %-13s %-25s' % \ ('species', 'period', 'height', 'weight', 'volume') print(s) # Then the table contents for sp in humans: d = humans[sp] period = d['period'] height = d['height'] weight = d['weight'] volume = d['volume'] s = '%-23s %-13s %-13s %-13s %-25s' % \ (sp, period, height, weight, volume) print(s)