Rod Derakhshanian
Rod Derakhshanian

Reputation: 51

How can I group items into collections stored as dictionary values?

So this is my code right now,

def course_rolls(records):
    """Returns course code as a key and then the
    student id as the value of the key"""
    course_roll_dict = {}
    for (course, student) in records:
        course_code = course[0]
        student_id = student[0]
        course_roll_dict.update({course_code:{student_id}})

and my output is

{'ENG002': {2721815},
 'FCOM02': {2113869},
 'ECO001': {2721815},
 'MTH001': {2923516},
 'ENG001': {2113869},
 'PHY001': {2949099},
 'GEL001': {2113869},
 'INF001': {2286481},
 'FCOM03': {2923516}}

but that is not the right output I want, I need to to be

{'ECO001': {2923516, 2721815},
 'ENG002': {2721815},
 'FCOM03': {2923516},
 'GEL001': {2113869},
 'FCOM02': {2113869},
 'PHY001': {2949099},
 'ENG001': {2923516, 2113869},
 'MTH001': {2923516},
 'INF001': {2286481}}

I just don't know how to give a key 2 values because there is two of the same key but two different values (or student ID's you could say). I'm for looping through text file. If I print out the course code and student ID, I get this:

ENG002 2721815
FCOM02 2113869
ECO001 2923516
MTH001 2923516
ECO001 2721815
ENG001 2923516
PHY001 2949099
GEL001 2113869
INF001 2286481
ENG001 2113869
FCOM03 2923516

Upvotes: 2

Views: 66

Answers (3)

Paul Cornelius
Paul Cornelius

Reputation: 10946

Dictionaries have the exact function you need - it's setdefault. Change the last line of your code to this:

course_roll_dict.setdefault(course_code, set()).add(student_id)

Here's what this weird-looking line of code does. setdefault attempts to find the key course_code in the dictionary. If the key isn't there, it adds the key to the dictionary and uses the second argument (an empty set) as the value, which at also returns. If the key is there, it just returns the value. In either case, the returned value is the set of students processed so far. Then you just add the new student to it.

You might also take a look at the class defaultdict in the standard library.

Upvotes: 2

Chiheb Nexus
Chiheb Nexus

Reputation: 9257

You can also use groupby from itertools module in order to solve your question, like this example:

from itertools import groupby

with open("my_file", 'r') as f:
    data = [k.split() for k in f.read().splitlines()]

course_roll_dict = {}

for k,v in groupby(sorted(data), lambda x: x[0]):
    course_roll_dict[k] = set(j[1] for j in v)

print(course_roll_dict)

Output:

{'ENG001': {'2113869', '2923516'}, 'FCOM03': {'2923516'}, 'INF001': {'2286481'}, 'ECO001': {'2721815', '2923516'}, 'ENG002': {'2721815'}, 'GEL001': {'2113869'}, 'FCOM02': {'2113869'}, 'PHY001': {'2949099'}, 'MTH001': {'2923516'}}

Upvotes: 1

Akavall
Akavall

Reputation: 86208

It looks like you are using update where you should use add:

This is what you have:

In [11]: my_dict = {"a": set((1,)), "b": set((2,))}

In [12]: my_dict.update({"a":set((3,))})

In [13]: my_dict
Out[13]: {'a': {3}, 'b': {2}}

This is what you want:

In [14]: my_dict = {"a": set((1,)), "b": set((2,))}

In [15]: my_dict["a"].add(3)

In [16]: my_dict
Out[16]: {'a': {1, 3}, 'b': {2}}

Upvotes: 2

Related Questions