5

I have one defaultdict(list) and other normal dictionary

A = {1:["blah", "nire"], 2:["fooblah"], 3:["blahblah"]}
B = {1: "something" ,2:"somethingsomething"}

now lets say that i have something like this

missing_value = "fill_this"

Now, first I want to find what are the keys in B missing from A (like 3 is missing) and then set those keys to the values missing_value? What is the pythonic way to do this? Thanks

4 Answers 4

13

You can use setdefault:

for k in A:
    B.setdefault(k, "fill_this")

This is essentially the same as the longer:

for k in A:
    if k not in B:
        B[k] = "fill_this"

However, since setdefault only needs to lookup each k once, setdefault is faster than this "test&set" solution.

Alternatively (and probably slower), determine the set difference and set (no pun intended) those values:

for k in set(A).difference(B):
    B[k] = "fill_this"
Sign up to request clarification or add additional context in comments.

5 Comments

hi.. what if A is a defaultdict(list) (sorry missed this in original description.. mybad)
Then it works just as well. defaultdict implements its own setdefault.
I think it sould be if k not in B.
B.setdefault could even be put out of the loop in some name e.x. B_set_def to avoid methods lookups on B.
Caching B.setdefault is probably premature optimization. It's explicitly mentioned in Dubious Python.
1

The solution is to go through A and update B where necessary. It would have O(len(A)) complexity:

for key in A:
    if key not in B:
        B[key] = missing_value

2 Comments

hi.. what if A is a defaultdict(list) (sorry missed this in original description.. mybad)
@phihag You are right about the needless creating of set in memory. I've already updated the answer to reflect that. set(A)-set(b) is O(len(A)) complexity because the algorithm goes through set(A) and looks for each element of set(A) if it's in set(B) which is O(1) for each element. But eventually you are right :) Because before the sets are subtracted, set(B) is created which is O(len(B)). I'll update the answer.
1

Here's one way:

def test():
    A = {1:"blah", 2:"fooblah", 3:"blahblah"}
    B = {1: "something" ,2:"somethingsomething"}
    keys=set(A.keys()).difference(set(B.keys()))
    for k in keys:
        B[k]="missing"
    print (B)

Comments

-1

When I've seen a need for this, there were a standard set of keys to be checked in a dict of dicts. If that's the case and if performance is not a significant factor, I think this is the cleanest syntax.

template = {k: default for k in domain}
for k, d in dicts.items():
    dicts[k] = template.copy().update(d)

1 Comment

This is actually wrong, of course, because update() doesn't return the updated dict. Fixing it makes it a bit less concise, but still a useful pattern.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.