I have a solution to this question, but I'm curious if there might be a better way.
I have a dict like this:
dict1 = {
'key1':[['value1','value2','value3'],['value4','value5','value6']],
'key2':[['value7','value8','value9'],['value10','value11','value12']],
'key3':[['value13','value14','value15'],['value16','value17','value18']]}
I want to convert this into a nested list, and inserting the keys into the new sublist like this:
nestedlist = [
['value1','value2','key1','value3'],['value4','value5','key1','value6'],
['value7','value8','key1','value9'],['value10','value11','key2','value12'],
['value13','value14','key2','value15'],['value16','value17','key2','value18'],
['value10','value11','key3','value12'],['value13','value14','key3','value15'],
['value16','value17','key3','value18']]
I solve this the following way:
keys = [*dict1]
newlist = []
for item in keys:
for item2 in dict1[item]:
item2.insert(2,item)
newlist.append(item2)
so, how can i improve this piece of code?
Here is one way via a list comprehension:
res = [[w[0], w[1], k, w[2]] for k, v in dict1.items() for w in v]
# [['value1', 'value2', 'key1', 'value3'],
# ['value4', 'value5', 'key1', 'value6'],
# ['value7', 'value8', 'key2', 'value9'],
# ['value10', 'value11', 'key2', 'value12'],
# ['value13', 'value14', 'key3', 'value15'],
# ['value16', 'value17', 'key3', 'value18']]
I would've done it pretty similarly. The only differences shown here:
result = []
for k, l in dict1.items():
for ll in l:
ll.insert(2, k)
result.append(ll)
No need to do list unpacking or doing [] accessing on dict1. items() returns a list of tuples containing each key and value of the dict.
Related
this is what my dict looks like:
ranked_imgs = {'d57b26aa-c8f8-4e08-9e8f-8aecd6e952a5': {'small': [],
'medium': [['https://www.pablo-ruiz-picasso.net/images/works/261.jpg', 1]],
'large': []},
'b10ecfdb-f590-4930-9975-aa12dc267f2f': {'small': [],
'medium': [],
'large': [['https://www.pablo-ruiz-picasso.net/images/works/3936.jpg', 1]]},......}
This is what I'm trying to do using dict comprehension but it fails because the temporary list is over ridden due to for loop:
dct = {k:[x for x in vv] for k,v in ranked_imgs.items() for vk,vv in v.items()}
or something like this maybe :
dct = {k:sum(vv,[]) for k,v in ranked_imgs.items() for vk,vv in v.items()}
This is what the code will look like with comprehension:
# ranked_imgs_={}
# for k,v in ranked_imgs.items():
# lst = []
# for vk,vv in v.items():
# for url in vv:
# lst.append(url)
# ranked_imgs_[k] = lst
I'm curious to know if there is a pythonic way to do this using dict comprehension!
Your expected output is a dict of lists, so you can use a list comprehension as the output value of a dict comprehension. Also note that you can iterate over v.values() instead of v.items() since you aren't using the keys (thanks to #MechanicPig for pointing it out):
dct = {k: [url for vv in v.values() for url in vv] for k, v in ranked_imgs.items()}
Use chain.from_iterable may be a little better than the answer of #blhsing, it iterates by concatenating v.values():
from itertools import chain
result = {k: list(chain.from_iterable(v.values())) for k, v in ranked_imgs.items()}
I have two dictionaries like this:
my_nested_dictionary= {'key5': 'value5',
'key6': {'inner_key6_1': 'inner_value6_1'},
'key7': 'value7'}
empty_dict = {}
If I want to update empty_dict with an inner dict from my_nested_dictionary, I can do that with this code:
for key, value in my_nested_dictionary.iteritems():
if key=='key6':
empty_dictionary.update(value)
However, is there any universal way to do this without using an 'if condition' hardcoded for exactly one key? If I had more nested dictionaries as a value of more keys in my_nested_dictionary, is there a way to update empty_dictionary with all of them at once?
If you don't need to update an existing dictionary and just want a dictionary containing only nested dictionaries, you can do this instead:
only_nested = {k: v for k, v in my_nested_dictionary.items() if isinstance(v, dict)}
For example, given this code:
my_nested_dictionary = {'key5': 'value5',
'key6': {'inner_key6_1': 'inner_value6_1'},
'key7': 'value7',
'key8': {'inner_key8_1': 'inner_value8_1'}}
only_nested = {k: v for k, v in my_nested_dictionary.items() if isinstance(v, dict)}
print(only_nested)
We get this output:
{'key6': {'inner_key6_1': 'inner_value6_1'}, 'key8': {'inner_key8_1': 'inner_value8_1'}}
If you want to check a nested dictionary;
for key, value in my_nested_dictionary.iteritems():
if isinstance(value, dict):
empty_dictionary.update(value)
If you would like to get just get the keys in one statement without using a if, you can do it like (Python 3):
output = list(filter(lambda key: isinstance(my_nested_dictionary[key], dict), my_nested_dictionary.keys()))
output will be like ['key 7'].
From there, you can look it up the vales from the original dictionary as you like. This way you don't have to multiple copies of the same objects.
given a dictionary with N keys and a tuple of K keys, K<=N is there a pythonic way to get a dictionary with only the K keys?
ex.
orig_dict = {'key1':'value1', 'key2':'value2', ..., 'keyN':'valueN'}
tuple = ('key2', 'keyM')
newdict = myFunc(orig_dict, tuple)
print newdict
Output:
'key2':'value2', 'keyM':'valueM'
You can use a dictionary comprehension:
{k:v for k,v in orig_dict.iteritems() if k in tuple_keys}
Observe:
>>> orig_dict = {'key1':'value1', 'key2':'value2', 'keyN':'valueN'}
>>> tuple_keys = ('key2', 'keyN')
>>> {k:v for k,v in orig_dict.iteritems() if k in tuple_keys}
{'keyN': 'valueN', 'key2': 'value2'}
Just use a comprehension:
tple = ('key2', 'keyM')
{k: orig_dict[k] for k in tple}
Or if you prefer functional:
from operator import itemgetter
dict(zip(tple, itemgetter(*tple)(orig_dict)))
What is more pythonic is debatable, what is definitely not pythonic is using tuple as a variable name.
If some keys may not exist you can get the intersection with viewkeys:
dict(zip(tuple, itemgetter(*orig_dict.viewkeys() & tple)(orig_dict)))
{k : orig_dict[k] for k in orig_dict.viewkeys() & tple}
For python3 just use .keys() which returns a dict_view object as opposed to a list in python2.
If you wanted to give a default value of None for missing keys, you could also use map with dict.get so missing keys would have their value set to None.
dict(zip(tuple, map(orig_dict.get, tuple)
Use a dictionary comprehension
orig_dict = {'key1':'value1', 'key2':'value2', 'keyN':'valueN'}
keys = ('key2', 'keyM')
>>> {k:orig_dict[k] for k in keys if k in orig_dict}
{'key2': 'value2'}
This will be more efficient than iterating over the dictionary's keys and checking whether the key exists in the tuple because it is an O(1) operation to lookup a dict vs O(n) to search in a tuple.
Alternatively you can use a set to get the common keys and combine that with a dict comprehension:
>>> {k:orig_dict[k] for k in set(keys).intersection(orig_dict)}
{'key2': 'value2'}
I need to do a not "natural" operation on a dictionary so i wondering what is the best pythonic way to do this.
I need to simplify a dictionary by removing all the keys on it with the same value (keys are differents, values are the same)
For example:
Input:
dict = {key1 : [1,2,3], key2: [1,2,6], key3: [1,2,3]}
expected output:
{key1 : [1,2,3], key2:[1,2,6]}
I dont care about which key is delete (on the example: key1 or key3)
Exchange keys and values; duplicated key-value pairs will be removed as a side effect (because dictionary does not allow duplicated keys). Exchange keys and values again.
>>> d = {'key1': [1,2,3], 'key2': [1,2,6], 'key3': [1,2,3]}
>>> d2 = {tuple(v): k for k, v in d.items()} # exchange keys, values
>>> d = {v: list(k) for k, v in d2.items()} # exchange again
>>> d
{'key2': [1, 2, 6], 'key1': [1, 2, 3]}
NOTE: tuple(v) was used because list is not hashable; cannot be used as key directly.
BTW, don't use dict as a variable name. It will shadow builtin function/type dict.
This solution deletes the keys with same values without creating a new dictionary.
seen = set()
for key in mydict.keys():
value = tuple(mydict[key])
if value in seen:
del mydict[key]
else:
seen.add(value)
I think you can do it this way also. But I don't say as there seems to be more efficient ways. It is in-line.
for i in dictionary.keys():
if dictionary.values().count(dictionary[i]) > 1:
del dictionary[i]
You can iterate over your dict items and use a set to check what we have seen so far, deleting a key if we have already seen the value:
d = {"key1" : [1,2,3], "key2": [1,2,6], "key3": [1,2,3]}
seen = set()
for k, v in d.items(): # list(items) for python3
temp = tuple(v)
if temp in seen:
del d[k]
seen.add(temp)
print(d)
{'key1': [1, 2, 3], 'key2': [1, 2, 6]}
This will be more efficient that using creating a dict and reversing the values as you only have to cast to tuple once not from a tuple back to a list.
this worked for me:
seen = set()
for key in mydict.copy():
value = tuple(mydict[key])
if value in seen:
del mydict[key]
else:
seen.add(value)
I'm new to Python and stuck at something basic.
Say there's a list of dictionaries as follows:
[{key1:value1},{key2:value2},...{keyn:valuen}]
is there a pythonic way of extracting the dictionary
{key1:value1},{key2:value2},...{keyn:valuen}
I'm assuming you mean that you want {key1: value1, key2:value2, keyn:valuen}. That is, you want to combine all the separate dictionaries into a single one with each of the keys and values from the individual dictionaries.
Here's how I'd do it, using a dictionary comprehension:
l = [{"key1":"value1"},{"key2":"value2"},{"keyn":"valuen"}]
result = {k:v for d in l for k, v in d.iteritems()}
print result # {'key2': 'value2', 'key1': 'value1', 'keyn': 'valuen'}
Same thing, in perhaps an easier way to read:
result = {}
d_list = [{"key1": "value1"}, {"key2": "value2"}, {"keyn": "valuen"}]
for d in d_list:
for k, v in d.iteritems():
result[k] = v
a=[{1:1},{2:2},{3:3}]
result=dict([(k,v) for x in a for k,v in x.items()])
print result //{1: 1, 2: 2, 3: 3}