1

I have four things to push to a dict user_post_dict with a method push_to_dict

user_post_dict= {}

def push_to_dict(user_email, post_id, question_text, question_answer):
    if user_email in user_post_dict:
        if post_id in user_post_dict[user_email]:
            user_post_dict[user_email][post_id][question_text] = question_answer
        else:
            user_post_dict[user_email][post_id] = {}
            user_post_dict[user_email][post_id][question_text] = question_answer
    else:
        user_post_dict[user_email] = {}
        user_post_dict[user_email][post_id] = {}
        user_post_dict[user_email][post_id][question_text] = question_answer

push_to_dict('abc@gmail.com',1,'what is this?', 'this is something')
push_to_dict('abc@gmail.com',2,'what is that?', 'that is something')
push_to_dict('def@gmail.com',1,'what is this?', 'this is something')
push_to_dict('def@gmail.com',2,'what is that?', 'that is something')

Is there any better way to optimize the code or shortening the code.

Shubham Nagota
  • 187
  • 1
  • 11
  • Does this answer your question? [Multi-level defaultdict with variable depth?](https://stackoverflow.com/questions/5369723/multi-level-defaultdict-with-variable-depth) – Nizar Jan 13 '20 at 14:00
  • 2
    Note that since you are not assigning a new value to the variable `user_post_dict` itself, neither your code or any of the answers need `global user_post_dict`. – Alex Hall Jan 13 '20 at 14:01

4 Answers4

5

You can use defaultdict

from collections import defaultdict


user_post_dict= defaultdict(lambda : defaultdict(defaultdict))


def push_to_dict(user_email, post_id, question_text, question_answer):
    user_post_dict[user_email][post_id][question_text] = question_answer
Anis Smail
  • 707
  • 7
  • 22
1

Yes, there are multiple possibilties. The best "in spirit" answer is defaultdict as shown by the other posts. But honestly, the data structure sucks to work with and is not easiliy testable. For one, you should pass the argument in, not use a global variable. Otherwise, testing and reusing will be problematic. Further, a class structure could be better to encapsulate the data and provide easier access.

Christian Sauer
  • 10,351
  • 10
  • 53
  • 85
  • I agree that the dict should be passed as a parameter, but creating a class for this is un-necessary and the benefits are not obvious so that would be an ideologically driven decision. – Anis Smail Jan 13 '20 at 14:10
  • @AnisSmail better encapsulation (separating the interface from the inner implementation) and easier access are "obvious benefits" IMHO. But I agree that we don't have enough context to decide whether this is relevant here or not ;-) – bruno desthuilliers Jan 13 '20 at 15:16
  • I know you are honest, I also agree that we don't have enough context here. But generally I would advise a straigh forward solution like a simple function. Separating the interface from the implementation is achievable using just a function, it also provide a very understandable abstraction, using a class would be the first step to an over-engineered solution. – Anis Smail Jan 13 '20 at 15:47
0
user_post_dict = {}


def push_to_dict(user_email, post_id, question_text, question_answer):
    user_post_dict.setdefault(user_email, {}).setdefault(post_id, {})[question_text] = question_answer


push_to_dict('abc@gmail.com', 1, 'what is this?', 'this is something')
push_to_dict('abc@gmail.com', 2, 'what is that?', 'that is something')
push_to_dict('def@gmail.com', 1, 'what is this?', 'this is something')
push_to_dict('def@gmail.com', 2, 'what is that?', 'that is something')

assert user_post_dict == {'abc@gmail.com': {1: {'what is this?': 'this is something'},
                                            2: {'what is that?': 'that is something'}},
                          'def@gmail.com': {1: {'what is this?': 'this is something'},
                                            2: {'what is that?': 'that is something'}}}
Alex Hall
  • 34,833
  • 5
  • 57
  • 89
0
user_post_dict= {}
def push_to_dict(user_email, post_id, question_text, question_answer):
    global user_post_dict
    if user_email not in user_post_dict:
        user_post_dict.update({user_email:{post_id:{}}})

    if post_id not in user_post_dict[user_email]:
        user_post_dict[user_email].update({post_id:{question_text: question_answer}})
    else:
        user_post_dict[user_email][post_id][question_text] = question_answer

push_to_dict('abc@gmail.com',1,'what is this?', 'this is something')
push_to_dict('abc@gmail.com',2,'what is that?', 'that is something')
push_to_dict('def@gmail.com',1,'what is this?', 'this is something')
push_to_dict('def1@gmail.com',5,'what is that?', 'that is something')
Ritesh Bisht
  • 182
  • 6