Nested Lists and Comprehensions

In the last lecture, we introduced file reading using the with ... as block. Today, we will focus on reading CSV files, storing the data as list of lists, and analyzing it using list and string methods to compute important properties.

Recall that we have written a few helper functions for working with strings, which are now in a module sequenceTools:

  • isVowel(character): returns True or False if character is a vowel

  • countVowels(word): returns number of vowels in word (int)

  • wordStartEnd(wordList): Takes a list of words and returns the list of words in it that start and end with the same letter

  • palindromes(wordList): Takes a list of words and returns the list of words in it that are palindromes

We will use them as we work through the some examples.

from sequenceTools import *

List Comprehensions to Map and Filter

When processing lists, there are common patterns that come up:

Mapping. Iterate over a list and return a new list which results from performing an operation on each element of a given list

  • E.g., take a list of integers numList and return a new list which contains the square of each number in numList

Filtering. Iterate over a list and return a new list that results from keeping those elements of the list that satisfy some condition

  • E.g., take a list of integers numList and return a new list which contains only the even numbers in numList

Python allows us to implement these patterns succinctly using list comprehensions.

numList = range(10)

# generate list of even numbers without list comprehension:
evens = []
for num in numList:
    if num % 2 == 0:
        evens.append(num)
print(evens)
[0, 2, 4, 6, 8]
# same computation as above, but with a list comprehension
# evens is a new list
numList = range(10)
evens = [num for num in numList if num % 2 == 0]
print(evens)
[0, 2, 4, 6, 8]
# mapping and filtering together
# create a list of even numbers squared
numList = range(10)
evenSquared = [num**2 for num in numList if num % 2 == 0]
print(evenSquared)
[0, 4, 16, 36, 64]

Student Facts with List Comprehensions

In the last class we were working with student data to compute some “interesting” facts about our names. Let’s see how we can use list comprehensions to simplify some of our tasks.

# first let's create our student list
students = [] # initialize empty list
filename = "csv/classNames.csv"
with open(filename) as roster: 
    for line in roster:
        fullName = line.strip().split(',')
        firstName = fullName[1]
        lastName = fullName[0]
        students.append(firstName + ' ' + lastName)
students
['RJ Acosta',
 'Harris Agha',
 'Nick R. Alcock',
 'Emir C. Atli',
 'Daniel Y. Chang',
 'Keelan S. Durham',
 'Timothy E. Felten',
 'Kyle E. Gwilt',
 'Sarah A. Hartman',
 'Brij C. Howard-Sarin',
 'Weiran Jiang',
 'Matt L. Joy',
 'Mikey A. Keyes',
 'Reona Kubomiya',
 'Gabe Lee',
 'Yuri J. Lee',
 'Trung Nguyen T. Nguyen',
 'Kunal Pal',
 'Min Kyu Park',
 'Betsy Paul',
 'Matthew L. Phang',
 'Leah Rubinshteyn',
 'Jennifer R. Sarmiento',
 'Alyse Sayed',
 'Aniya J. Smith',
 'Nevin D. Vilandrie',
 'Harrison P. Williams',
 'Jordan A. Wynn',
 'Tryphena Bossman',
 'Nora E. Brant',
 'Alex W. Choi',
 'Harry Cross',
 'Edith N. Edwards-Mizel',
 'Amir H. Estejab',
 'Arden N. Fluehr',
 'Lesley C. Iazzag',
 'Patrick Izidro',
 'Sameer Jain',
 'Miranda C. Kimm',
 'Noah J. Kroninger',
 'Arielle T. Levy',
 'Myer C. Liebman',
 'Julia M. Matin',
 'Jack D. Napeloni',
 'Natalia H. Nolan',
 'Jaquelin T. Nordhoff',
 'Reece K. Overholt',
 'Tiffany J. Park',
 'Doug J. Pineda Gutierrez',
 'Priya Rajbhandary',
 'Gautam Ramasamy',
 'Genevieve B. Randazzo',
 'Kimberly Rogers',
 'Sam Samuel',
 'Maximilian A. Shah',
 'Matt R. Shareshian',
 'Marta G. Symkowick',
 'Rein T. Vaska',
 'C.J. Vilfort',
 'Olivia V. Winters',
 'Matt Wisotsky',
 'Rick Yanashita',
 'Skylar O. Yarter',
 'Nicole S. Zhou',
 'Addison Zou',
 'Jackson C. Adelman',
 'Valeria Aragon',
 'M Aditta Arian',
 'Martina Berrutti Bartesaghi',
 'Anjali K. Bhatia',
 'Ryan T. Cass',
 'Kayla Chang',
 'Will J. Chen',
 'Grace A. Clarke',
 'Ethan Cooper',
 'Felix L. Diaz',
 'Pedro R. Espinosa',
 'Leilani Fuentes',
 'Jane C. Gutchess',
 'Sasha G. Horvath',
 'Kevin Y. Jiang',
 'Riya Juneja',
 'Lena O. Kerest',
 'Prom Kingchatchaval',
 'Rebekah A. Lindsay',
 'Jade Lowe',
 'Grace K. Maffei',
 'Emma C. Miller',
 'Paige E. Nelson',
 'Kendall L. Rice',
 'Hari Shankaran',
 'Gurinder Singh',
 'Ella G. Sukup',
 'Ruby J. Yager',
 'Winnie Zhang']
# calculate which names start with a vowel, without list comprehension
vowelNames = []
for name in students:
    if isVowel(name[0]):
        vowelNames.append(name)
      
vowelNames
['Emir C. Atli',
 'Alyse Sayed',
 'Aniya J. Smith',
 'Alex W. Choi',
 'Edith N. Edwards-Mizel',
 'Amir H. Estejab',
 'Arden N. Fluehr',
 'Arielle T. Levy',
 'Olivia V. Winters',
 'Addison Zou',
 'Anjali K. Bhatia',
 'Ethan Cooper',
 'Emma C. Miller',
 'Ella G. Sukup']
# calculate which names start with a vowel, with list comprehension
vowelNames = [name for name in students if isVowel(name[0])]

vowelNames
['Emir C. Atli',
 'Alyse Sayed',
 'Aniya J. Smith',
 'Alex W. Choi',
 'Edith N. Edwards-Mizel',
 'Amir H. Estejab',
 'Arden N. Fluehr',
 'Arielle T. Levy',
 'Olivia V. Winters',
 'Addison Zou',
 'Anjali K. Bhatia',
 'Ethan Cooper',
 'Emma C. Miller',
 'Ella G. Sukup']

Indexing Lists of Lists

List comprehensions also allow us to easily creates two-dimensional lists, or lists of lists. We can treat a list of lists just like we would a list of any other sequence (e.g. strings).

To index an element of an inner list, we’d need two indices:

  • first (leftmost) index identifies which inner list we want, and

  • second (rightmost) index identifies which element within that inner list we want.

filename = 'csv/classnames.csv' 
allStudents = []
with open(filename) as roster:
    for student in roster:
        allStudents.append(student.strip().split(','))
allStudents # list of list of strings
[['Acosta', 'RJ', '26', 'rja3'],
 ['Agha', 'Harris', '25', 'hha1'],
 ['Alcock', 'Nick R.', '25', 'nra2'],
 ['Atli', 'Emir C.', '26', 'eca2'],
 ['Chang', 'Daniel Y.', '25', 'dyc1'],
 ['Durham', 'Keelan S.', '25', 'ksd2'],
 ['Felten', 'Timothy E.', '26', 'tef2'],
 ['Gwilt', 'Kyle E.', '25', 'kg15'],
 ['Hartman', 'Sarah A.', '25', 'sah4'],
 ['Howard-Sarin', 'Brij C.', '26', 'bch6'],
 ['Jiang', 'Weiran', '26', 'wj4'],
 ['Joy', 'Matt L.', '26', 'mlj2'],
 ['Keyes', 'Mikey A.', '26', 'mak5'],
 ['Kubomiya', 'Reona', '26', 'rk20'],
 ['Lee', 'Gabe', '26', 'gjl1'],
 ['Lee', 'Yuri J.', '26', 'yjl1'],
 ['Nguyen', 'Trung Nguyen T.', '26', 'ttn2'],
 ['Pal', 'Kunal', '25', 'kp12'],
 ['Park', 'Min Kyu', '23', 'mp14'],
 ['Paul', 'Betsy', '26', 'bep4'],
 ['Phang', 'Matthew L.', '23', 'mlp6'],
 ['Rubinshteyn', 'Leah', '26', 'lr15'],
 ['Sarmiento', 'Jennifer R.', '23', 'jrs14'],
 ['Sayed', 'Alyse', '26', 'ats5'],
 ['Smith', 'Aniya J.', '26', 'ajs20'],
 ['Vilandrie', 'Nevin D.', '25', 'ndv1'],
 ['Williams', 'Harrison P.', '26', 'hpw2'],
 ['Wynn', 'Jordan A.', '26', 'jaw10'],
 ['Bossman', 'Tryphena', '26', 'tb13'],
 ['Brant', 'Nora E.', '25', 'neb2'],
 ['Choi', 'Alex W.', '26', 'awc6'],
 ['Cross', 'Harry', '25', 'hc11'],
 ['Edwards-Mizel', 'Edith N.', '25', 'ene1'],
 ['Estejab', 'Amir H.', '26', 'ahe3'],
 ['Fluehr', 'Arden N.', '25', 'anf1'],
 ['Iazzag', 'Lesley C.', '26', 'lci1'],
 ['Izidro', 'Patrick', '23', 'pi2'],
 ['Jain', 'Sameer', '23', 'sj8'],
 ['Kimm', 'Miranda C.', '26', 'mck3'],
 ['Kroninger', 'Noah J.', '26', 'njk5'],
 ['Levy', 'Arielle T.', '26', 'atl5'],
 ['Liebman', 'Myer C.', '26', 'mcl4'],
 ['Matin', 'Julia M.', '25', 'jmm15'],
 ['Napeloni', 'Jack D.', '25', 'jdn3'],
 ['Nolan', 'Natalia H.', '26', 'nhn1'],
 ['Nordhoff', 'Jaquelin T.', '24', 'jtn1'],
 ['Overholt', 'Reece K.', '24', 'rko1'],
 ['Park', 'Tiffany J.', '23', 'tjp4'],
 ['Pineda Gutierrez', 'Doug J.', '25', 'djp5'],
 ['Rajbhandary', 'Priya', '25', 'pr5'],
 ['Ramasamy', 'Gautam', '26', 'gr6'],
 ['Randazzo', 'Genevieve B.', '25', 'gbr3'],
 ['Rogers', 'Kimberly', '24', 'kjr5'],
 ['Samuel', 'Sam', '26', 'ss45'],
 ['Shah', 'Maximilian A.', '26', 'mas25', ''],
 ['Shareshian', 'Matt R.', '25', 'mrs8'],
 ['Symkowick', 'Marta G.', '25', 'mgs6'],
 ['Vaska', 'Rein T.', '25', 'rtv1'],
 ['Vilfort', 'C.J.', '24', 'cjv3'],
 ['Winters', 'Olivia V.', '25', 'ow2'],
 ['Wisotsky', 'Matt', '23', 'mjw7'],
 ['Yanashita', 'Rick', '26', 'ry5'],
 ['Yarter', 'Skylar O.', '25', 'soy1'],
 ['Zhou', 'Nicole S.', '25', 'nsz1'],
 ['Zou', 'Addison', '25', 'az7'],
 ['Adelman', 'Jackson C.', '25', 'jca4'],
 ['Aragon', 'Valeria', '26', 'va2'],
 ['Arian', 'M Aditta', '26', 'ma20'],
 ['Berrutti Bartesaghi', 'Martina', '24', 'mb30'],
 ['Bhatia', 'Anjali K.', '25', 'akb5'],
 ['Cass', 'Ryan T.', '24', 'rtc1'],
 ['Chang', 'Kayla', '25', 'kc27'],
 ['Chen', 'Will J.', '25', 'wjc3'],
 ['Clarke', 'Grace A.', '23', 'gac3'],
 ['Cooper', 'Ethan', '23', 'ec15'],
 ['Diaz', 'Felix L.', '26', 'fld1'],
 ['Espinosa', 'Pedro R.', '26', 'pre1'],
 ['Fuentes', 'Leilani', '24', 'lf5'],
 ['Gutchess', 'Jane C.', '25', 'jcg5'],
 ['Horvath', 'Sasha G.', '25', 'sgh3'],
 ['Jiang', 'Kevin Y.', '26', 'kyj1'],
 ['Juneja', 'Riya', '26', 'rj6'],
 ['Kerest', 'Lena O.', '25', 'hok1'],
 ['Kingchatchaval', 'Prom', '26', 'pk8'],
 ['Lindsay', 'Rebekah A.', '25', 'ral2'],
 ['Lowe', 'Jade', '26', 'jl42'],
 ['Maffei', 'Grace K.', '25', 'gkm1'],
 ['Miller', 'Emma C.', '26', 'ecm5'],
 ['Nelson', 'Paige E.', '26', 'pen1'],
 ['Rice', 'Kendall L.', '25', 'klr6'],
 ['Shankaran', 'Hari', '26', 'hs14'],
 ['Singh', 'Gurinder', '26', 'gs14'],
 ['Sukup', 'Ella G.', '26', 'egs2'],
 ['Yager', 'Ruby J.', '25', 'rjy1'],
 ['Zhang', 'Winnie', '26', 'wz4']]
allStudents[0] # list of first student's info
['Acosta', 'RJ', '26', 'rja3']
allStudents[0][1] # how do I index RJ's first name?
'RJ'
# now with a list comprehension
filename = 'csv/classnames.csv' 
with open(filename) as roster:
    allStudents = [student.strip().split(',') for student in roster] 
allStudents # a list of lists of strings!
[['Acosta', 'RJ', '26', 'rja3'],
 ['Agha', 'Harris', '25', 'hha1'],
 ['Alcock', 'Nick R.', '25', 'nra2'],
 ['Atli', 'Emir C.', '26', 'eca2'],
 ['Chang', 'Daniel Y.', '25', 'dyc1'],
 ['Durham', 'Keelan S.', '25', 'ksd2'],
 ['Felten', 'Timothy E.', '26', 'tef2'],
 ['Gwilt', 'Kyle E.', '25', 'kg15'],
 ['Hartman', 'Sarah A.', '25', 'sah4'],
 ['Howard-Sarin', 'Brij C.', '26', 'bch6'],
 ['Jiang', 'Weiran', '26', 'wj4'],
 ['Joy', 'Matt L.', '26', 'mlj2'],
 ['Keyes', 'Mikey A.', '26', 'mak5'],
 ['Kubomiya', 'Reona', '26', 'rk20'],
 ['Lee', 'Gabe', '26', 'gjl1'],
 ['Lee', 'Yuri J.', '26', 'yjl1'],
 ['Nguyen', 'Trung Nguyen T.', '26', 'ttn2'],
 ['Pal', 'Kunal', '25', 'kp12'],
 ['Park', 'Min Kyu', '23', 'mp14'],
 ['Paul', 'Betsy', '26', 'bep4'],
 ['Phang', 'Matthew L.', '23', 'mlp6'],
 ['Rubinshteyn', 'Leah', '26', 'lr15'],
 ['Sarmiento', 'Jennifer R.', '23', 'jrs14'],
 ['Sayed', 'Alyse', '26', 'ats5'],
 ['Smith', 'Aniya J.', '26', 'ajs20'],
 ['Vilandrie', 'Nevin D.', '25', 'ndv1'],
 ['Williams', 'Harrison P.', '26', 'hpw2'],
 ['Wynn', 'Jordan A.', '26', 'jaw10'],
 ['Bossman', 'Tryphena', '26', 'tb13'],
 ['Brant', 'Nora E.', '25', 'neb2'],
 ['Choi', 'Alex W.', '26', 'awc6'],
 ['Cross', 'Harry', '25', 'hc11'],
 ['Edwards-Mizel', 'Edith N.', '25', 'ene1'],
 ['Estejab', 'Amir H.', '26', 'ahe3'],
 ['Fluehr', 'Arden N.', '25', 'anf1'],
 ['Iazzag', 'Lesley C.', '26', 'lci1'],
 ['Izidro', 'Patrick', '23', 'pi2'],
 ['Jain', 'Sameer', '23', 'sj8'],
 ['Kimm', 'Miranda C.', '26', 'mck3'],
 ['Kroninger', 'Noah J.', '26', 'njk5'],
 ['Levy', 'Arielle T.', '26', 'atl5'],
 ['Liebman', 'Myer C.', '26', 'mcl4'],
 ['Matin', 'Julia M.', '25', 'jmm15'],
 ['Napeloni', 'Jack D.', '25', 'jdn3'],
 ['Nolan', 'Natalia H.', '26', 'nhn1'],
 ['Nordhoff', 'Jaquelin T.', '24', 'jtn1'],
 ['Overholt', 'Reece K.', '24', 'rko1'],
 ['Park', 'Tiffany J.', '23', 'tjp4'],
 ['Pineda Gutierrez', 'Doug J.', '25', 'djp5'],
 ['Rajbhandary', 'Priya', '25', 'pr5'],
 ['Ramasamy', 'Gautam', '26', 'gr6'],
 ['Randazzo', 'Genevieve B.', '25', 'gbr3'],
 ['Rogers', 'Kimberly', '24', 'kjr5'],
 ['Samuel', 'Sam', '26', 'ss45'],
 ['Shah', 'Maximilian A.', '26', 'mas25', ''],
 ['Shareshian', 'Matt R.', '25', 'mrs8'],
 ['Symkowick', 'Marta G.', '25', 'mgs6'],
 ['Vaska', 'Rein T.', '25', 'rtv1'],
 ['Vilfort', 'C.J.', '24', 'cjv3'],
 ['Winters', 'Olivia V.', '25', 'ow2'],
 ['Wisotsky', 'Matt', '23', 'mjw7'],
 ['Yanashita', 'Rick', '26', 'ry5'],
 ['Yarter', 'Skylar O.', '25', 'soy1'],
 ['Zhou', 'Nicole S.', '25', 'nsz1'],
 ['Zou', 'Addison', '25', 'az7'],
 ['Adelman', 'Jackson C.', '25', 'jca4'],
 ['Aragon', 'Valeria', '26', 'va2'],
 ['Arian', 'M Aditta', '26', 'ma20'],
 ['Berrutti Bartesaghi', 'Martina', '24', 'mb30'],
 ['Bhatia', 'Anjali K.', '25', 'akb5'],
 ['Cass', 'Ryan T.', '24', 'rtc1'],
 ['Chang', 'Kayla', '25', 'kc27'],
 ['Chen', 'Will J.', '25', 'wjc3'],
 ['Clarke', 'Grace A.', '23', 'gac3'],
 ['Cooper', 'Ethan', '23', 'ec15'],
 ['Diaz', 'Felix L.', '26', 'fld1'],
 ['Espinosa', 'Pedro R.', '26', 'pre1'],
 ['Fuentes', 'Leilani', '24', 'lf5'],
 ['Gutchess', 'Jane C.', '25', 'jcg5'],
 ['Horvath', 'Sasha G.', '25', 'sgh3'],
 ['Jiang', 'Kevin Y.', '26', 'kyj1'],
 ['Juneja', 'Riya', '26', 'rj6'],
 ['Kerest', 'Lena O.', '25', 'hok1'],
 ['Kingchatchaval', 'Prom', '26', 'pk8'],
 ['Lindsay', 'Rebekah A.', '25', 'ral2'],
 ['Lowe', 'Jade', '26', 'jl42'],
 ['Maffei', 'Grace K.', '25', 'gkm1'],
 ['Miller', 'Emma C.', '26', 'ecm5'],
 ['Nelson', 'Paige E.', '26', 'pen1'],
 ['Rice', 'Kendall L.', '25', 'klr6'],
 ['Shankaran', 'Hari', '26', 'hs14'],
 ['Singh', 'Gurinder', '26', 'gs14'],
 ['Sukup', 'Ella G.', '26', 'egs2'],
 ['Yager', 'Ruby J.', '25', 'rjy1'],
 ['Zhang', 'Winnie', '26', 'wz4']]
len(allStudents) # number of students in class
95

List Comprehension Exercises

Let’s complete the following tasks using list comprehensions.

  1. Generate a list of only student last names.

# generate list of only student last names
lastNames = [s[0] for s in allStudents]
lastNames
['Acosta',
 'Agha',
 'Alcock',
 'Atli',
 'Chang',
 'Durham',
 'Felten',
 'Gwilt',
 'Hartman',
 'Howard-Sarin',
 'Jiang',
 'Joy',
 'Keyes',
 'Kubomiya',
 'Lee',
 'Lee',
 'Nguyen',
 'Pal',
 'Park',
 'Paul',
 'Phang',
 'Rubinshteyn',
 'Sarmiento',
 'Sayed',
 'Smith',
 'Vilandrie',
 'Williams',
 'Wynn',
 'Bossman',
 'Brant',
 'Choi',
 'Cross',
 'Edwards-Mizel',
 'Estejab',
 'Fluehr',
 'Iazzag',
 'Izidro',
 'Jain',
 'Kimm',
 'Kroninger',
 'Levy',
 'Liebman',
 'Matin',
 'Napeloni',
 'Nolan',
 'Nordhoff',
 'Overholt',
 'Park',
 'Pineda Gutierrez',
 'Rajbhandary',
 'Ramasamy',
 'Randazzo',
 'Rogers',
 'Samuel',
 'Shah',
 'Shareshian',
 'Symkowick',
 'Vaska',
 'Vilfort',
 'Winters',
 'Wisotsky',
 'Yanashita',
 'Yarter',
 'Zhou',
 'Zou',
 'Adelman',
 'Aragon',
 'Arian',
 'Berrutti Bartesaghi',
 'Bhatia',
 'Cass',
 'Chang',
 'Chen',
 'Clarke',
 'Cooper',
 'Diaz',
 'Espinosa',
 'Fuentes',
 'Gutchess',
 'Horvath',
 'Jiang',
 'Juneja',
 'Kerest',
 'Kingchatchaval',
 'Lindsay',
 'Lowe',
 'Maffei',
 'Miller',
 'Nelson',
 'Rice',
 'Shankaran',
 'Singh',
 'Sukup',
 'Yager',
 'Zhang']
  1. Generate a list of only student first names.

# List comprehension to generate a list of first names 
# (without middle initial)
firstNames = [s[1].split()[0] for s in allStudents]
firstNames
['RJ',
 'Harris',
 'Nick',
 'Emir',
 'Daniel',
 'Keelan',
 'Timothy',
 'Kyle',
 'Sarah',
 'Brij',
 'Weiran',
 'Matt',
 'Mikey',
 'Reona',
 'Gabe',
 'Yuri',
 'Trung',
 'Kunal',
 'Min',
 'Betsy',
 'Matthew',
 'Leah',
 'Jennifer',
 'Alyse',
 'Aniya',
 'Nevin',
 'Harrison',
 'Jordan',
 'Tryphena',
 'Nora',
 'Alex',
 'Harry',
 'Edith',
 'Amir',
 'Arden',
 'Lesley',
 'Patrick',
 'Sameer',
 'Miranda',
 'Noah',
 'Arielle',
 'Myer',
 'Julia',
 'Jack',
 'Natalia',
 'Jaquelin',
 'Reece',
 'Tiffany',
 'Doug',
 'Priya',
 'Gautam',
 'Genevieve',
 'Kimberly',
 'Sam',
 'Maximilian',
 'Matt',
 'Marta',
 'Rein',
 'C.J.',
 'Olivia',
 'Matt',
 'Rick',
 'Skylar',
 'Nicole',
 'Addison',
 'Jackson',
 'Valeria',
 'M',
 'Martina',
 'Anjali',
 'Ryan',
 'Kayla',
 'Will',
 'Grace',
 'Ethan',
 'Felix',
 'Pedro',
 'Leilani',
 'Jane',
 'Sasha',
 'Kevin',
 'Riya',
 'Lena',
 'Prom',
 'Rebekah',
 'Jade',
 'Grace',
 'Emma',
 'Paige',
 'Kendall',
 'Hari',
 'Gurinder',
 'Ella',
 'Ruby',
 'Winnie']

Aside: Generating random indices. Python gives us a convenient way to generate random numbers using the random module.

import random # import module to help generate random numbers
randomIndex = random.randint(0, 76)  
# generates a random integer between 0 and 76 (inclusive!!)
randomIndex = random.randint(0, 76)  
allStudents[randomIndex] # great way to cold call!  :-)
['Samuel', 'Sam', '26', 'ss45']
allStudents[random.randint(0,76)][1]   
# Accessing just the first name (and middle initial)
'Patrick'

Student Fun Facts!

Let’s use our student list to get some practice with lists of lists and useful string and list methods.

  1. Write a function characterList which takes in two arguments rosterList (list of lists) and character (a string) and returns the list of students in the class whose name starts with character.

def characterList(rosterList, character):
    """Takes the student info as a list of lists and a 
    string character and returns a list of students whose 
    first name starts with character"""
    return [name[1] for name in rosterList if name[1][0] == character]
characterList(allStudents, "B")
['Brij C.', 'Betsy']
  1. Write a function that can be used to compute the list of student(s) with the most vowels in their first name. (Hint: use countVowels().)

def mostVowels(wordList):
    '''Takes a list of strings wordList and returns a list
    of strings from wordList that contain the most # vowels'''
    # initialize max to be low
    maxVowels = -1
    # initialize an accumumlator of names
    results = []

    # for each name, count vowels (value)
    for word  in wordList:
        numVowels = countVowels(word)

        # find a value > max, update max
        if numVowels > maxVowels:
            maxVowels = numVowels
            # if value > max, then re-initialize the list
            results = [word]
        elif numVowels == maxVowels:
            # if value == max, then append
            results.append(word)

    return results
    
# which student(s) has most vowels in their name?
mostVowelNames = mostVowels(firstNames)  
mostVowelNames
['Genevieve', 'Maximilian']
def mostVowels(wordList):
    '''Takes a list of strings wordList and returns a list
    of strings from wordList that contain the most # vowels'''
    
    maxSoFar = 0 # initialize counter
    result = []
    for word in wordList:
        count = countVowels(word)
        if count > maxSoFar:
            # update: found a better word
            maxSoFar = count
            result = [word] 

        elif count == maxSoFar:  
            result.append(word)
    return result
# which student(s) has most vowels in their name?
mostVowelNames = mostVowels(firstNames)  
mostVowelNames
['Genevieve', 'Maximilian']

LEAST VOWELS

def leastVowels(wordList):
    '''Takes a list of strings wordList and returns a list
    of strings from wordList that contain the least # vowels'''
    # init min be high value
    minVowels = 10000

    # init accumulator of names
    results = []

    # for each name in list
    for word in wordList:
        # count vowels
        numVowels = countVowels(word)
        # if count < min, update min & reinit accumulator
        if numVowels < minVowels:
            minVowels = numVowels
            results = [word]
        # else if count == min, append new name
        elif numVowels == minVowels:
            results.append(word)

    # return results!
    return results
# which student(s) has least vowels in their name?
leastVowelNames = leastVowels(firstNames)  
leastVowelNames
['RJ', 'C.J.', 'M']
  1. We can use our helper function to find out which word(s) have the most number of vowels in other word lists, too.

songWords = []
with open('textfiles/mountains.txt') as song:  
    for line in song:
        songWords.extend(line.strip().split())

mostVowels(songWords)
['mountain',
 'peaceful',
 'mountains!',
 'mountains!',
 'rebounding',
 'fountains',
 'peaceful',
 'mountains',
 'mountain',
 'mountains!',
 'mountains!',
 'rebounding',
 'fountains']
  1. Write a function that can be used to compute the student with the least vowels in their last name.

def leastVowels(wordList):
    '''Takes a list of strings wordList and returns a list
    of strings in wordList that contain the least number of vowels'''
    minSoFar = len(wordList[0]) # initialize counter
    result = []
    for word in wordList:
        count = countVowels(word)
        if count < minSoFar:
            # update: found a better word
            minSoFar = count
            result = [word] 

        elif count == minSoFar:  
            result.append(word)
    return result
leastVowelNames = leastVowels(firstNames)
leastVowelNames
['RJ', 'C.J.', 'M']
  1. Write a function yearList which takes in two arguments rosterList (list of lists) and year (int) and returns the list of students in the class with that graduating year.

def yearList(rosterList, year):
    """Takes the student info as a list of lists and a year (22-26)
    and returns a list of students graduating that year"""
    return [name[1]+" "+name[0] for name in rosterList if name[2] == str(year)]
seniors = yearList(allStudents, 23)
seniors
['Min Kyu Park',
 'Matthew L. Phang',
 'Jennifer R. Sarmiento',
 'Patrick Izidro',
 'Sameer Jain',
 'Tiffany J. Park',
 'Matt Wisotsky',
 'Grace A. Clarke',
 'Ethan Cooper']

More Lists of Lists: Ballots!

In Lab 4, you’ll work with lists of lists of strings in the form of ballots. An example is shown below.

# different types of coffee
filename = 'csv/coffee.csv' 
with open(filename) as coffeeTypes:
    allCoffee = []
    for coffee in coffeeTypes:
        allCoffee.append(coffee.strip().split(','))
allCoffee
[['kona', 'dickason', 'ambrosia', 'wonderbar', 'house'],
 ['kona', 'house', 'ambrosia', 'wonderbar', 'dickason'],
 ['kona', 'ambrosia', 'dickason', 'wonderbar', 'house'],
 ['kona', 'ambrosia', 'wonderbar', 'dickason', 'house'],
 ['house', 'kona', 'dickason', 'wonderbar', 'ambrosia'],
 ['kona', 'house', 'dickason', 'ambrosia', 'wonderbar'],
 ['kona', 'house', 'dickason', 'ambrosia', 'wonderbar'],
 ['dickason', 'ambrosia', 'wonderbar', 'kona', 'house'],
 ['house', 'kona', 'ambrosia', 'dickason', 'wonderbar'],
 ['ambrosia', 'house', 'wonderbar', 'kona', 'dickason'],
 ['wonderbar', 'ambrosia', 'kona', 'house', 'dickason'],
 ['house', 'wonderbar', 'kona', 'ambrosia', 'dickason']]
allCoffee[0] # access first "inner" list
['kona', 'dickason', 'ambrosia', 'wonderbar', 'house']
allCoffee[1] # access second inner list 
['kona', 'house', 'ambrosia', 'wonderbar', 'dickason']
allCoffee[0][1] # access second element in first inner list
'dickason'
# access second character of second element of first inner list 
allCoffee[0][1][1] 
'i'
# create list of only last elements of inner lists
lastCoffee = [coffee[-1] for coffee in allCoffee] 
lastCoffee
['house',
 'dickason',
 'house',
 'house',
 'ambrosia',
 'wonderbar',
 'wonderbar',
 'house',
 'wonderbar',
 'dickason',
 'dickason',
 'dickason']
# how many last place votes did wonderbar get?
lastCoffee.count("wonderbar")
3