Edit dictionary values if keys found in list - python

Is there a cleaner way to do this? Could I accomplish this via list comprehension?
data = {'foo': 'bar', 'twofoo': 'twobar', 'threefoo': 'threebar'}
some_list = ['foo', 'threefoo']
for key in data:
for item in some_list:
if key==item:
data[key] = 'randomfoo'
I want to clean the values from a dictionary
so 'random foo' will always be the same
Care to elaborate on the downvotes?

You can take the intersection of the dictionary keys with the list, and update values at those keys:
for key in set(data).intersection(some_list):
data[key] = 'foobar'
print(data)
# {'twofoo': 'twobar', 'threefoo': 'foobar', 'foo': 'foobar'}
You could also define your list as a set and do a quick membership check (with O(1) complexity) for each key:
some_set = {'foo', 'threefoo'}
for key in data:
if key in some_set:
data[key] = 'randomfoo'

Using dict comprehension:
res = {key: 'randomfoo' if key in some_list else value for key, value in data.items()}
Output:
>>> res
{'twofoo': 'twobar', 'threefoo': 'randomfoo', 'foo': 'randomfoo'}

You can try this way :
data = {'foo': 'bar', 'twofoo': 'twobar', 'threefoo': 'threebar'}
some_list = ['foo', 'threefoo']
for key in data:
if key in some_list:
data[key] = "randomfoo"
print(data)
Output:
{'foo': 'randomfoo', 'twofoo': 'twobar', 'threefoo': 'randomfoo'}

Related

Delete certain keys from a nested dictionary using dictionary comprehension

I have to work with a nested dictionary filled with numbers in python 'my_dict', and a list that specifies the subkeys 'keys 'that have to be deleted:
keys=[1,9]
my_dict={1:{1:a, 2:b}, 2:{1:c, 3:d, 9:e}}
I want to have two outcomes:
Delete all subkeys+their values if they are in keys, e.g.
new_dict={1:{2:b}, 2:{3:d}}
Or Delete all subkeys+their values if they are not in keys, e.g.
new_dict:{1:{1:a}, 2:{1:c,9:e}}
I have tried:
new_list = {outer_k: {inner_k: inner_v for inner_k, inner_v in outer_v.items()-{1,9}} for outer_k, outer_v in my_dict.items()}
It gives me back the same dict without deletion of the elements, same for the second szenario
new_list = {outer_k: {inner_k: inner_v for inner_k, inner_v in outer_v.items()&{1,9}} for outer_k, outer_v in my_dict.items()}
I have also tried:
for key, value in my_dict.items():
for key1, value1 in value.items():
for key1 in keys:
try:
del dict[key1]
except KeyError:
pass
This gives me the error:
TypeError: 'type' object does not support item deletion
I would be glad if anyone knows of a neat solution for this!
Using dict comprehension:
new_dict = {k_out : {k_in : v_in for k_in, v_in in v_out.items() if k_in in keys} for k_out,v_out in my_dict.items()}
The error TypeError: 'type' object does not support item deletion stems from
for key, value in my_dict.items():
for key1, value1 in value.items():
for key1 in keys:
try:
del dict[key1] # this is the build in, not your instance
# fix: del my_dict[key1]
except KeyError:
pass
As for the comprehensions - they look rather long ....
keys = [1,9]
my_dict = {1:{1:"a", 2:"b"}, 2:{1:"c", 3:"d", 9:"e"}}
# delete top levels
# for unwanted_key in keys:
# try:
# del my_dict[unwanted_key]
# except KeyError:
# pass
# delete inside sub levels
for unwanted_key in keys:
for inner_key in my_dict:
try:
del my_dict[inner_key][unwanted_key]
except KeyError:
pass
print( my_dict)
Results in
# {2: {3: 'd'}} # if you do top level and sub level
{1: {2: 'b'}, 2: {3: 'd'}} # if you only do sub levels
The try: ... except: ... follows "Ask forgiveness not permission" - explain
For your example , i recreated the data to runnable,
however deleting directly from the dict you' re iterating on will throw an error , you can do it by creating a copy of a dictionary where will your result will be stored
keys=[1,9]
my_dict={1:{1:"a", 2:"b"}, 2:{1:"c", 3:"d", 9:"e"}}
my_dict
new_dict1=my_dict.copy()
for key, value in my_dict.items():
if key1 in value.keys() and key1 in keys:
# delete subkeys and their sub values
del new_dict1[key][key1]
You can modify my_dict in situ like this:
keys = [1, 9]
my_dict = {1: {1: 'a', 2: 'b'}, 2: {1: 'c', 3: 'd', 9: 'e'}}
for v in my_dict.values():
for k in keys:
if k in v:
del v[k]
print(my_dict)
Output:
{1: {2: 'b'}, 2: {3: 'd'}}

Python - Return the dictionary key comparing dictionary values with list

I was trying to compare a list with dictionary values to see if they match so I could return the key, but I couldn't find a solution to match them:
>>> my_dict = {'A': ['apple', 'america'], B: ['bee', 'bar'], C: ['car','cake','cat'], D: ['dad']}
>>> my_list = ['apple', 'dad']
In this case, the result would be:
['A', 'D']
What would be the best approach? I tried a nested for-loop, but I was wondering if there is a more direct answer.
my_second_dict = {}
for key in my_dict.keys():
for values in my_dict[key]:
I am not really sure how to do it. I'd appreciate your help.
Thanks!
You have a list of values and you want the keys of the dictionary items that have those values in their values (which are lists of values). This is assuming there are no duplicates in the lists in the dictionary (which seems reasonable, since it appears to group them by initial).
This is a solution:
my_dict = {'A': ['apple', 'america'], 'B': ['bee', 'bar'], 'C': ['car','cake','cat'], 'D': ['dad']}
my_list = ['apple', 'dad']
my_result = [k for v in my_list for k, vs in my_dict.items() if v in vs]
print(my_result)
Result:
['A', 'D']
Do you mean something like this?
my_dict = {'A': ['apple', 'america'], B: ['bee', 'bar'], C: ['car','cake','cat'], D: ['dad']}
my_list = ['apple', 'dad']
results = []
for key in my_dict.keys():
for value in my_list:
if value in my_dict[key]:
results.append(key)
break
print(results)
Loop through the keys in the dictionary, and check if any of the values in the list are in the dictionary.
You do not need to use the break statement if you use set intersection or list comprehension.
my_dict = {'A': ['apple', 'america'], B: ['bee', 'bar'], C: ['car','cake','cat'], D: ['dad']}
my_list = ['apple', 'dad']
results = []
for key in my_dict.keys():
if set(my_list).intersection(set(dict[key])):
results.append(key)
print(results)
my_dict = {'A': ['apple', 'america'], B: ['bee', 'bar'], C: ['car','cake','cat'], D: ['dad']}
my_list = ['apple', 'dad']
results = []
for key in my_dict.keys():
if any([val in my_dict[key] for val in my_list]):
results.append(key)
print(results)
I think if you finish your loop, you can end up with something like this:
output = []
for i in my_list:
for k, v in my_dict.items():
if i in v:
output.append(k)
or a one-liner
output = [k for i in my_list for k, v in my_dict.items() if i in v]

Group list of dict results using python based on first key from each item

I am trying to find the output of this list of dict using Python. Because foo and data are unique keys, the output should merge them.
input = [{'foo': 'foo-main-123'}, {'foo': 'foo-main-345'}, {'data': 'data-main-111'}]
output = {'foo', ['foo-main-123', 'foo-main-345'], 'data': ['data-main-111']}
you can use defaultdict(list), then iterate each k,v pair in each dict in input.
try this:
from collections import defaultdict
input = [{'foo': 'foo-main-123'}, {'foo': 'foo-main-345'}, {'data': 'data-main-111'}]
output = defaultdict(list)
for d in input:
for k,v in d.items():
output[k].append(v)
output=dict(output)
print(output)
Output:
{'foo': ['foo-main-123', 'foo-main-345'], 'data': ['data-main-111']}

python create dict using list of strings with length of strings as values

I'm sure this can be done, but I have thus far been unsuccessful:
I have a list of strings. I want to create a dictionary with the length of said strings (which can be expressed as a range) as the key and the string itself as the value.
example:
Here's something like the list I have: ['foo','bar','help','this','guy']
I'd like to end up with a dictionary like this:
{3:['foo','bar','guy], 4:['this','help']}
Using defaultdict so you don't have to check whether or not to create the list for a new key:
from collections import defaultdict
x = ['foo','bar','help','this','guy']
len_dict = defaultdict(list)
for word in x:
len_dict[len(word)].append(word)
len_dict
#
# Out[5]: defaultdict(list, {3: ['foo', 'bar', 'guy'], 4: ['help', 'this']})
You can use a dictionary as a container with setdefault:
lst = ['foo','bar','help','this','guy']
result = {}
for w in lst:
result.setdefault(len(w), []).append(w)
result
# {3: ['foo', 'bar', 'guy'], 4: ['help', 'this']}
You can do it like that:
d={}
lst=['foo','bar','help','this','guy']
for i in lst:
if len(i) in d:
d[len(i)].append(i)
else:
d[len(i)]=[i]
This solution is pythonic, elegant and fast: (by the Famous Raymond Hettinger in one of his many conferences).
dict.setdefault is the dictionary method that initialises a key-value if the key is not found in dict as well as performing dict.get for provided key.
l = ['foo','bar','help','this','guy']
d = {}
for e in l:
key = len(e)
d.setdefault(key, []).append(name)
print(d)
Output:
{3: ['foo', 'bar', 'guy'], 4: ['help', 'this']}
This solution is the modern way of the solution above:
defaultdict from collection is a subclass of dict that automatically initialises value to any given key that is not in the defaultdict.
from collections import defaultdict
l = ['foo','bar','help','this','guy']
d = defaultdict(list)
for e in l:
key = len(e)
d[key].append(e)
print(d)
Output:
defaultdict(<class 'list'>, {3: ['foo', 'bar', 'guy'], 4: ['help', 'this']})
Similar to what have been said, but using the get method of dict class:
the_list=['foo','bar','help','this','guy']
d = {}
for word in the_list:
key = len(word)
d[key] = d.get(key, []) + [word]
print(d)
# {3: ['foo', 'bar', 'guy'], 4: ['help', 'this']}
Another approach:
from collections import defaultdict
given_list=['foo','bar','help','this','guy']
len_words=[len(i) for i in given_list]
d=defaultdict(list)
for i,j in list(zip(len_words,given_list)):
d[i].append(j)

Split on whitespaces in keys of dict, take value

I have a dictionary which has this form:
myDict = {'foo': bar, 'foobar baz': qux}
Now, I want to split on whitespaces in the key of the dict, make it the next key and take the value (duplicate).
myDictRev1 = {'foo': bar, 'foobar': qux, 'baz': qux}
You can use dictionary comprehensions like this:
>>> myDict = {'foo': 'bar', 'foobar baz': 'qux'}
>>> {k:v for k, v in myDict.items() for k in k.split()}
{'baz': 'qux', 'foo': 'bar', 'foobar': 'qux'}

Categories