ahsan mukhtar
ahsan mukhtar

Reputation: 442

Find all keys which match multiple values in dictionary

I have a dictionary which looks like this.

dics = {'classes':[
            {"class_number":'CIS41A', 'topic':'Python Programming', 'start_time':'8:30 AM', 'time_category':'Early Morning'},
            {"class_number":'CIS41A', 'topic':'Java Programming', 'start_time':'11:30 AM', 'time_category':'Late Morning'} ,
            {"class_number":'CIS41J', 'topic':'Python Programming', 'start_time':'8 PM', 'time_category':'Evening'},
            {"class_number":'CIS41A', 'topic':'Linear Programming', 'start_time':'6 PM', 'time_category':'Evening'}
                ]
    }

I want to yield class_number that have topics 'Python Programming','Java Programming' and Linear Programming

So output will be CIS41A

Upvotes: 1

Views: 155

Answers (2)

Boseong Choi
Boseong Choi

Reputation: 2596

Is this what you wnat?

from collections import defaultdict

dic = {
    'classes': [
        {"class_number": 'CIS41A', 'topic': 'Python Programming',
         'start_time': '8:30 AM', 'time_category': 'Early Morning'},
        {"class_number": 'CIS41A', 'topic': 'Java Programming',
         'start_time': '11:30 AM', 'time_category': 'Late Morning'},
        {"class_number": 'CIS41J', 'topic': 'Python Programming',
         'start_time': '8 PM', 'time_category': 'Evening'},
        {"class_number": 'CIS41A', 'topic': 'Linear Programming',
         'start_time': '6 PM', 'time_category': 'Evening'},
        {"class_number": 'CIS41A', 'topic': 'Fourth Topic',
         'start_time': '9 PM', 'time_category': 'Evening'},
    ]
}


def gen(mandatory_topics: set):
    topic_dict = defaultdict(set)
    passed_classes = set()
    for class_ in dic['classes']:
        class_num = class_['class_number']
        topic_dict[class_num].add(class_['topic'])
        if topic_dict[class_num] >= mandatory_topics and class_num not in passed_classes:
            passed_classes.add(class_num)
            yield class_num


topics = {'Python Programming', 'Java Programming', 'Linear Programming'}

for item in gen(topics):
    print(item)

output:

CIS41A

I add 5th data for testing corner case.


Additional edit

I need to pass the topic as individual arguments (like *args) not as a lists or sets. How can I change this code according?

Change parameter and add code converting its type.

def gen(*mandatory_topics: str):
    mandatory_topics = set(mandatory_topics)

Upvotes: 1

user2390182
user2390182

Reputation: 73450

You can do the following, using a collections.defaultdict and set intersection:

from collections import defaultdict

check = {'Java Programming', 'Python Programming', 'Linear Programming'}

def gen(dics):
    topics = defaultdict(set)
    for klass in dics['classes']:
        topics[klass['class_number']].add(klass['topic'])
    for klass_number in topics:
        if topics[klass_number] & check == check:
            yield klass_number

>>> list(gen(dics))
['CIS41A']

Upvotes: 2

Related Questions