Reputation: 39
Hello there i m very new in python and i think like c# and i cant do some things. I have this list for ex.
data = [["Bob","Algebra",5],["Bob","History",4],["Bob","Physics",7],["Bob","Astronomy",5],["Allen","Algebra",5],["Allen","History",4],["Allen","Physics",7],["Mary","Algebra",5],["Mary","History",3],["Mary","Physics",7],["Mary","Astronomy",8]
]
How i make this output from that:
MathsPerStudent = [["Bob","Algebra","History","Physics","Astronomy"]
["Allen","Algebra","History","Physics"]
["Mary","Algebra","History","Physics","Astronomy"]]
As i see i cant have
MathsPerStudents=[[]]
for i in data:
for j in MathsPerStudents:
if data[i][0] == j[0]
MathsPerStudents.append(j[0][i])
and with some way to fill the MathPerStudents correctly. As i can see data[i] cant compare with j[i] because the one is list the other is int from element. The point is in for loop how could i use (i) as index in a list like data list.
Upvotes: 0
Views: 70
Reputation: 922
That's exactly what defaultdict
can be used for:
from collections import defaultdict
subjects_by_name = defaultdict(list) # if element is missing in the dict, it will be a list
for name, subject, _ in data:
subjects_by_name[name].append(subject)
MathsPerStudents = [[name, *subjects] for name, subjects in subjects_by_name.items()] # make a list of lists out of a dict
As you can see it is similar to @Rakesh's answer. As @pallgeuer pointed out, it would be easier to work with a dict instead of converting it to a list of lists. Get used to dicts in python as soon as you can!
Upvotes: 0
Reputation: 1884
You could use itertools.groupby
if your list of lists is ordered by names:
import itertools
data = [["Bob","Algebra",5],["Bob","History",4],["Bob","Physics",7],["Bob","Astronomy",5],["Allen","Algebra",5],["Allen","History",4],["Allen","Physics",7],["Mary","Algebra",5],["Mary","History",3],["Mary","Physics",7],["Mary","Astronomy",8]]
output = []
for student, classes in itertools.groupby(data, key=lambda x: x[0]):
output.append([student] + [entry[1] for entry in classes])
print(output)
Upvotes: 2
Reputation: 1366
You can do something like this (not a one-liner, but maybe easier to understand):
MathsPerStudent = {}
for name, subject, grade in data:
if name not in MathsPerStudent:
MathsPerStudent[name] = []
MathsPerStudent[name].append(subject)
This gives you a dictionary:
>>> from pprint import pprint
>>> pprint(MathsPerStudent)
{'Allen': ['Algebra', 'History', 'Physics'],
'Bob': ['Algebra', 'History', 'Physics', 'Astronomy'],
'Mary': ['Algebra', 'History', 'Physics', 'Astronomy']}
If you want you can then convert it to list form, but probably the dictionary would be easier to work with for whatever you're trying to achieve:
MathsPerStudentList = [[name] + subjects for name, subjects in MathsPerStudent.items()]
Here the final list:
>>> pprint(MathsPerStudentList)
[['Bob', 'Algebra', 'History', 'Physics', 'Astronomy'],
['Allen', 'Algebra', 'History', 'Physics'],
['Mary', 'Algebra', 'History', 'Physics', 'Astronomy']]
Upvotes: 2
Reputation: 82765
Using setdefault
Ex:
data = [["Bob","Algebra",5],["Bob","History",4],["Bob","Physics",7],["Bob","Astronomy",5],["Allen","Algebra",5],["Allen","History",4],["Allen","Physics",7],["Mary","Algebra",5],["Mary","History",3],["Mary","Physics",7],["Mary","Astronomy",8]]
result = {}
for k, sub, _ in data:
result.setdefault(k, []).append(sub) #Set first element as key and append subject as value
print([[k] + v for k, v in result.items()]) #Form required list
Output:
[['Bob', 'Algebra', 'History', 'Physics', 'Astronomy'],
['Allen', 'Algebra', 'History', 'Physics'],
['Mary', 'Algebra', 'History', 'Physics', 'Astronomy']]
Upvotes: 2