15-112 Lecture 8 (Wednesday, June 5, 2013)

Download Source Code

Nested Collections Example

In class today we built an example that involved tuples, lists, and dictionaries. It also required file I/O. I've added additional comments to the source code to help you walk through it again. Please find it below.

collectionsExample.py


#!/usr/bin/python

JOBS_FILE = "jobs.txt"
PEOPLE_FILE = "people.txt"

tradeLookupTable = {}    # A dictionary
jobList = []             # A list

# Input: Name of a file and an empty list
# Result: Previously empty list holds a tuple of needed workers by type
# (number, trade)
def buildJobList(jobsFile,jobList):

  # Read jobs lines from input file
  inputFile = open(JOBS_FILE)
  jobLines = inputFile.readlines()

  # For job line, add it to the job list
  for jobLine in jobLines:

    # Parse the line
    jobRecords = jobLine.split(";")

    # Note the job name
    jobName = jobRecords[0]

    # Build the list of trades needed
    jobTalentList = []
    for jobRecord in jobRecords[1:]:
      # Split the record into people x trade
      (numberPeople,trade) = jobRecord.split(",")
      numberPeople = numberPeople.strip()
      trade = trade.strip()

      # Add peoplextrade to jobTalentList
      jobTalentList.append((numberPeople, trade))

    # Append a new job to the jobList
    jobList.append((jobName,jobTalentList))  # Notice we're adding a tuple to the list


# Input: Name of a file and an empty dictionary
# Result: Previously empty dictionary maps from trade name to a list of
# works in that trade
def buildTradeLookup(peopleFile,lookupTable):
  inputFile = open(peopleFile)

  personLines = inputFile.readlines()

  for personLine in personLines:
    fields = personLine.split(",")
    name = fields[0].rstrip().lstrip() # This could be a single strip()
    for fieldNumber in range (1,len(fields)):
      trade = fields[fieldNumber].strip() # Here we do it with one strip()

      # This catches the case where we haven't yet encountered someone
      # in this trade. In this case, there is no list, so the .append()
      # operation is being called upon None. But, of course, it isn't
      # defined upon None, so it blows up. 
      try:
        lookupTable[trade].append(name)
      except:
        # We catch the blow up, create and add the list, then append
        # The name to the newly created list
        lookupTable[trade] = []
        lookupTable[trade].append(name)

# Input: a dictionary mapping from the name fo a trade to a list of the 
# names of those in the trade, as well as a list of jobs, where each
# job within the list is a tuple specifying the (number, trade) number of
# people needed in each trade.
# Result: Prints (displays to user) that the job os "A-Okay", or the number 
# and kind for each treade where additional workers are needed
def verifyJobs(tradeLookupTable, jobList):
  for job in jobList:
    jobName = job[0]
    tradesNeeded = job[1]
    
    problemList = []
    for tradeNeeded in tradesNeeded:
      (numberNeeded, trade) = tradeNeeded
      try:

        # Note the cast int() below
        if (len(tradeLookupTable[trade]) < int(numberNeeded)):
          problemList.append((trade, len(tradeLookupTable[trade]) - int(numberNeeded)))
      except:
          problemList.append((trade, -1 * int(numberNeeded)))
      
    if (len(problemList) !=0 ):
      print "%s:" % (jobName),
      print problemList
    else:
      print "%s: A-Okay." % (jobName)


buildTradeLookup(PEOPLE_FILE, tradeLookupTable)
buildJobList(JOBS_FILE, jobList)
verifyJobs(tradeLookupTable, jobList)