I am trying to solve a problem which has to make a .csv file into list of lists (list1) and then I have to use map function to extract the desired output into another list (list2) from list1
the csv file contains data like
Last name, First name, Final, Grade
Alfalfa, Aloysius,49, D-
Alfred, University,48, D
After making the .csv into list I have to check for the marks if the student will be selected or not by using map on the list1
So here I code it like this
import csv
from curses.ascii import isdigit
def selection(lis):
for x in lis:
if(x.isdigit() and int(x) > 50):
return lis
list1=[]
list2=[]
with open('D:\C \Programs\Advanced Programming\grades.csv', 'r') as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader)
for line in csv_reader:
list1.append(line)
for i in list1:
r = map(selection, i)
R = list(r)
list2.append(R)
print(list1)
print(list2)
list1 prints correctly
[['Alfalfa', ' Aloysius', '49', ' D-'], ['Alfred', ' University', '48', ' D ']....]
But my list2 is printing
[[None, None, None, None], [None, None, None, None].....]
I am not getting how to use map on list of lists. Why it is printing none. Please help to solve it.
CodePudding user response:
just update ur selection function as
def selection(lis):
return lis if (lis.isdigit() and int(lis) > 50) else None
map sends a single item to the function not the entire list
Output will be
[['boo', 'foo', '53', 'a']]
[[None, None, '53', None]]
you can return anything else other than None if you want in selection function's else statement
CodePudding user response:
Issue #1
The first problem is that you are going a little too deep. The code
for i in list1:
r = map(selection, i)
is sending individual list items to selection when you are expecting the entire list to be sent to selection. You want to change that code to just be
r = map(selection, list1)
How this results in a bunch of Nones
If you add some print statements around the place to debug what is going on you would see that
for i in list1: makes i be a single list such as ['Alfalfa', ' Aloysius', '49', ' D-']
Then map sends each item from our list i to the selection function. So def selection(lis): doesn't actually recieve a list, it will receive an item from the list such as Alfalfa or 49.
Then we have for x in lis: where we check each character in Alfalfa to see if it is a number greater than 50. Is A greater than 5n, No. Is l greater than 50, no. And so on. The for loop finishes, and whenever a function finishes without returning anything, None is returned. Map then moves on to the next item in the list until it gets to a number such as 51 where it will check each character, a 5 and a 1 in this case. Since 5 is not greater than 50 and 1 is not greater than 50, we continue on. As you can see you will never end up with a number greater than 50 since we are in a little too deep checking each individual character instead of the whole item.
Issue #2
The second problem is you want to use filter instead of map to ignore anything that returns None. filter will loop over each item sending each item to selection and will add the item to our list r only if selection returns something true.
The following code does what you want.
import csv
def selection(lis):
for x in lis:
if(x.isdigit() and int(x) > 50):
return True
list1=[]
list2=[]
with open('D:\C \Programs\Advanced Programming\grades.csv', 'r') as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader)
for line in csv_reader:
list1.append(line)
r = filter(selection, i)
list2 = list(r)
print(list1)
print(list2)
How I'd solve this type of problem
Below is how I would go about solving this problem. I'm using list comprehension instead of map or filter.
import csv
csv_file = 'D:\C \Programs\Advanced Programming\grades.csv'
with open(csv_file) as fh:
csv_reader = csv.reader(fh)
headers = next(csv_reader)
data = list(csv_reader)
passing_grades = [x for x in data if x.isdigit() and int(x) > 50]
print('passing grades: ', passing_grades)
