Karajohann
Karajohann

Reputation: 39

Make 2d list from another 2d list with loops and if condition

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

Answers (4)

asikorski
asikorski

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

Talon
Talon

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

pallgeuer
pallgeuer

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

Rakesh
Rakesh

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

Related Questions