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
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"
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
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)
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)
Related
i was asked to write a code including a function- reverse_dict_in_place(d)
which switches between keys and values of the inputed dictionary
without changing the dictionary's location in memory (in place).
however, testing it with id() function shows that all my solutions do change dictionaries memory location..
def reverse_dict_in_place(d):
d={y:x for x,y in d.items()}
return d
Alternative to current ones which allows values to be same as keys. Works in mostly the same way though, however once again no two values may be the same.
def reverse_dict_in_place(d):
copy = d.copy().items()
d.clear()
for k, v in copy:
d[v] = k
return d
>>> x = {0: 1, 1: 2}
>>> y = reverse_dict_in_place(x)
>>> id(x) == id(y)
True
>>>
Some assumptions for this to work (thanks to all the users who pointed these out):
There are no duplicate values
There are no non-hashable values
There are no values that are also keys
If you're comfortable with those assumption then I think this should work:
def reverse_dict_in_place(d):
for k,v in d.items():
del d[k]
d[v] = k
return d
Extending on Gad suggestion, you could use dict comprehension:
reversed = {v: k for k, v in d.items()}
Where d is a dict, and the same assumptions apply:
There are no duplicate values
There are no non-hashable values
There are no values that are also keys
This would not work, without modification, for nested dicts.
Note: #NightShade has posted a similar answer as my below answer, earlier than I posted.
You can try this:
def reverse_dict_in_place(d):
d_copy = d.copy()
d.clear()
for k in d_copy:
d[d_copy[k]] = k
This would work even if one of the dictionary's values happens to also be a key (as tested out below)
Testing it out:
my_dict = {1:1, 2:'two', 3:'three'}
reverse_dict_in_place(my_dict)
print (my_dict)
Output:
{1: 1, 'two': 2, 'three': 3}
Is there a quicker way to write this:
def foo():
# What happens in here is irrelevant.
return new_value
dict['i_dont_want_to_type_this_twice'] = foo(dict['i_dont_want_to_type_this_twice'])
Like when you use x += 1
I don't think there's any built-in or standard library feature for this. The most idiomatic thing to do is probably define your own wrapper function, such as
def transform(d, k, f):
d[k] = f(d[k])
And then use it like so (note that I've renamed your dict to mydict to avoid masking the built-in):
transform(mydict, 'i_dont_want_to_type_this_twice', foo)
(I think apply() would make a decent name for this, but it's a built-in if you're using Python 2. Though it's been deprecated since 2.3, so there wouldn't be a lot of harm in it.)
You can do something like this, by using update on the dictionary.
d.update(a=foo(d.get('a', 0)))
Full demo:
d = {'a': 5}
def foo(val):
val += 100
return val
d.update(a=foo(d.get('a', 0)))
print(d) # outputs {'a': 105}
From the description of the dictionary update method:
D.update([E, ]**F) -> None. Update D from dict/iterable E and F.
If E is present and has a .keys() method, then does: for k in E: D[k] = E[k]
If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v
In either case, this is followed by: for k in F: D[k] = F[k]
So, if the key exists, it will update it, and if it does not, it will create it.
How about this for a one-liner assignment?
dict.update({key: foo(dict[key]) for key in ['i_dont_want_to_type_this_twice']})
Or, to update the entire dict:
dict = {k: foo(v) for k, v in dict.items()}
I have a dictionary like this :
d = {'v03':["elem_A","elem_B","elem_C"],'v02':["elem_A","elem_D","elem_C"],'v01':["elem_A","elem_E"]}
How would you return a new dictionary with the elements that are not contained in the key of the highest value ?
In this case :
d2 = {'v02':['elem_D'],'v01':["elem_E"]}
Thank you,
I prefer to do differences with the builtin data type designed for it: sets.
It is also preferable to write loops rather than elaborate comprehensions. One-liners are clever, but understandable code that you can return to and understand is even better.
d = {'v03':["elem_A","elem_B","elem_C"],'v02':["elem_A","elem_D","elem_C"],'v01':["elem_A","elem_E"]}
last = None
d2 = {}
for key in sorted(d.keys()):
if last:
if set(d[last]) - set(d[key]):
d2[last] = sorted(set(d[last]) - set(d[key]))
last = key
print d2
{'v01': ['elem_E'], 'v02': ['elem_D']}
from collections import defaultdict
myNewDict = defaultdict(list)
all_keys = d.keys()
all_keys.sort()
max_value = all_keys[-1]
for key in d:
if key != max_value:
for value in d[key]:
if value not in d[max_value]:
myNewDict[key].append(value)
You can get fancier with set operations by taking the set difference between the values in d[max_value] and each of the other keys but first I think you should get comfortable working with dictionaries and lists.
defaultdict(<type 'list'>, {'v01': ['elem_E'], 'v02': ['elem_D']})
one reason not to use sets is that the solution does not generalize enough because sets can only have hashable objects. If your values are lists of lists the members (sublists) are not hashable so you can't use a set operation
Depending on your python version, you may be able to get this done with only one line, using dict comprehension:
>>> d2 = {k:[v for v in values if not v in d.get(max(d.keys()))] for k, values in d.items()}
>>> d2
{'v01': ['elem_E'], 'v02': ['elem_D'], 'v03': []}
This puts together a copy of dict d with containing lists being stripped off all items stored at the max key. The resulting dict looks more or less like what you are going for.
If you don't want the empty list at key v03, wrap the result itself in another dict:
>>> {k:v for k,v in d2.items() if len(v) > 0}
{'v01': ['elem_E'], 'v02': ['elem_D']}
EDIT:
In case your original dict has a very large keyset [or said operation is required frequently], you might also want to substitute the expression d.get(max(d.keys())) by some previously assigned list variable for performance [but I ain't sure if it doesn't in fact get pre-computed anyway]. This speeds up the whole thing by almost 100%. The following runs 100,000 times in 1.5 secs on my machine, whereas the unsubstituted expression takes more than 3 seconds.
>>> bl = d.get(max(d.keys()))
>>> d2 = {k:v for k,v in {k:[v for v in values if not v in bl] for k, values in d.items()}.items() if len(v) > 0}
Is it possible to replace all values in a dictionary, regardless of value, with the integer 1?
Thank you!
Sure, you can do something like:
d = {x: 1 for x in d}
That creates a new dictionary d that maps every key in d (the old one) to 1.
You can use a dict comprehension (as others have said) to create a new dictionary with the same keys as the old dictionary, or, if you need to do the whole thing in place:
for k in d:
d[k] = 1
If you're really fond of 1-liners, you can do it in place using update:
d.update( (k,1) for k in d )
a = {1:2, 2:2,3:2}
a = {x:1 for (x,_) in a.iteritems()}
print a
{1: 1, 2: 1, 3: 1}
Yes, it's possible. Iterate through every key in the dictionary and set the related value to 1.
If a and b are 2 dictionaries:
a = {'UK':'http://www.uk.com', 'COM':['http://www.uk.com','http://www.michaeljackson.com']}
bb = {'Australia': 'http://www.australia.com', 'COM':['http://www.Australia.com', 'http://www.rafaelnadal.com','http://www.rogerfederer.com']}
I want to merge them to get
{'Australia': ['http://www.australia.com'], 'COM': ['http://www.uk.com', 'http://www.michaeljackson.com', 'http://www.Australia.com', 'http://www.rafaelnadal.com', 'http://www.rogerfederer.com'], 'UK': ['http://www.uk.com']}
I want to union them i.e.
How to do it in Python without overwwriting and replacing any value?
Use a defaultdict:
from collections import defaultdict
d = defaultdict(list)
for dd in (a,bb):
for k,v in dd.items():
#Added this check to make extending work for cases where
#the value is a string.
v = (v,) if isinstance(v,basestring) else v #basestring is just str in py3k.
d[k].extend(v)
(but this is pretty much what I told you in my earlier answer)
This now works if your input dictionaries look like
{'Australia':['http://www.australia.com']}
or like:
{'Australia':'http://www.australia.com'}
However, I would advise against the latter form. In general, I think it's a good idea to keep all the keys/values of a dictionary looking the same (at least if you want to treat all the items the same as in this question). That means that if one value is a list, it's a good idea for all of them to be a list.
If you really insist on keeping things this way:
d = {}
for dd in (a,b):
for k,v in dd.items():
if(not isinstance(v,list)):
v = [v]
try:
d[k].extend(v)
except KeyError: #no key, no problem, just add it to the dict.
d[k] = v