This question already has answers here:
Extract a subset of key-value pairs from dictionary?
(14 answers)
Closed 6 years ago.
I've a dictionary my_dict and a list of tokens my_tok as shown:
my_dict = {'tutor': 3,
'useful': 1,
'weather': 1,
'workshop': 3,
'thankful': 1,
'puppy': 1}
my_tok = ['workshop',
'puppy']
Is it possible to retain in my_dict, only the values present in my_tok rather than popping the rest?
i.e., I need to retain only workshop and puppy.
Thanks in advance!
Just overwrite it like so:
my_dict = {k:v for k, v in my_dict.items() if k in my_tok}
This is a dictionary comprehension that recreates my_dict using only the keys that are present as entries in the my_tok list.
As said in the comments, if the number of elemenst in the my_tok list is small compaired to the dictionary keys, this solution is not the most efficient one. In that case it would be much better to iterate through the my_tok list instead as follows:
my_dict = {k:my_dict.get(k, default=None) for k in my_tok}
which is more or less what the other answers propose. The only difference is the use of .get dictionary method with allows us not to care whether the key is present in the dictionary or not. If it isn't it would be assigned the default value.
Going over the values from the my_tok, and get the results that are within the original dictionary.
my_dict = {i:my_dict[i] for i in my_tok}
Create a new copy
You can simply overwrite the original dictionary:
new_dic = {token:my_dict[key] for key in my_tok if key in my_dict}
Mind however that you construct a new dictionary (perhaps you immediately writ it to my_dict) but this has implications: other references to the dictionary will not reflect this change.
Since the number of tokens (my_tok) are limited, it is probably better to iterate over these tokens and do a contains-check on the dictionary (instead of looping over the tuples in the original dictionary).
Update the original dictionary
Given you want to let the changes reflect in your original dictionary, you can in a second step you can .clear() the original dictionary and .update() it accordingly:
new_dic = {token:my_dict[key] for key in my_tok if key in my_dict}
my_dict.clear()
my_dict.update(new_dic)
Related
EDIT: My question has been getting a lot of follow up questions because on the surface, it doesn't appear to make any sense. For most people, dictionaries are an illogical way to solve this problem. I agree, and have been frustrated by my constraints (explained in the comments). In my scenario, the original KV pairs are going to be encoded as data to be read by another server using the ObjectID. This, however, must be fed into an encoding function as a dictionary. The order does not matter, but the KV pairs must be given a new unique value. The original KV pairs will end up as a new string key in this new dictionary with the ObjectID as a new unique value.
Keep in mind that I am using Python 2.7.
The Issue
Note that this is a matter of presenting a dictionary (dictA), encoded by the ObjectID values, within the constraints of what I have been given
I have a dictionary, say dictA = {'a':'10', 'b':'20', 'c':'30'}, and I have a list of ObjectIdentifier('n'), where n is a number. What is the best way to create dictB so that dictB is a new dictionary with the key equal to dictA's key:value pair and the value equal to the corresponding ObjectIdentifier('n') in the list.
The new dictB should be:
{"'a':'10'":ObjectIdentifier('n'), "'b':'20'":ObjectIdentifier('n+1'), "'c':'30'":ObjectIdentifier('n+2')}
If that makes any sense.
The problem is that dictionaries aren't ordered. So you say
dictA = {'a':'10', 'b':'20', 'c':'30'}
but as far as python knows it could be
dictA = {'c':'30', 'a':'10', 'b':'20'}
Because dictionaries don't have order.
You could create your dict like this:
result = {key: ObjectIdentifier(n+pos) for pos, key in enumerate(dictA.items())}
But there is no way to determine which key will fall in which position, because, as I said, dictionaries don't have order.
If you want alphabetic order, just use sorted()
result = {key: ObjectIdentifier(n+pos)
for pos, key in enumerate(sorted(dictA.items()))}
I don't know why you would want this
def ObjectIdentifier(n):
print(n)
return "ObjectIdentifier("+ str(n) + ")"
dictA = {'a':'10', 'b':'20', 'c':'30'}
dictB = {}
for n, key in enumerate(sorted(dictA.keys())):
dictB[key] = {dictA[key] : ObjectIdentifier(str(n))}
Output:
{'a': {'10': 'ObjectIdentifier(0)'}, 'b': {'20': 'ObjectIdentifier(1)'}, 'c': {'30': 'ObjectIdentifier(2)'}}
I have a dictionary with unique values and I want to invert it (i.e. swap keys with values) inplace.
Is there any way doing it without using another dictionary?
I would prefer to just manipulate the items inside the dict than use a new dictionary, so that id(my_dict) would remain the same.
If you are trying to swap keys and values and do not mind duplicate values creating key conflicts, you can "reverse" the dictionary rather easily with a single line of code:
dictionary = dict(map(reversed, dictionary.items()))
If you would rather use the dictionary comprehension syntax instead, you can write this line:
dictionary = {value: key for key, value in dictionary.items()}
If you do not want to use the items method of the dictionary, it is rather easy to avoid:
dictionary = {dictionary[key]: key for key in dictionary}
If you can afford creating a copy of the dictionary, you can reverse it in place if needed:
def reverse_in_place(dictionary):
reference = dictionary.copy()
dictionary.clear()
dictionary.update(map(reversed, reference.items()))
I guess you want to swap the keys and the values of the dict?
You can do it like this:
dict_name = dict(zip(dict_name.values(), dict_name.keys()))
This question already has an answer here:
deleting entries in a dictionary based on a condition
(1 answer)
Closed 8 years ago.
I'm trying to drop items from a dictionary if the value of the key is below a certain threshold. For a simple example to what I mean:
my_dict = {'blue': 1, 'red': 2, 'yellow': 3, 'green': 4}
for color in my_dict:
threshold_value = 3
if my_dict[color] < threshold_value:
del my_dict[color]
print(my_dict)
Now, I get a RuntimeError: dictionary changed size during iteration error. No big surprises there. The reason I'm posting this question is:
Find out if there's an elegant solution that doesn't require creating a new dictionary (that holds only the keys with values >= threshold).
Try to understand Python's rationale here. The way I read it to myself is: "go to the first key. Is the value of that key < x ? if yes - del this key:value item and continue on the the next key in the dictionary, if no - continue to next key without doing anything". In other words, what happened historically to previous keys shouldn't affect where I go next. I'm looking forward to the next items, regardless of the past.
I know it's a funny (some might say stupid, I'll give you that) but what's Python's "way of thinking" about this loop? Why doesn't it work? How would Python read it out loud to itself? Just trying to get a better understanding of the language...
Due to the fact that Python dictionaries are implemented as hash tables, you shouldn't rely on them having any sort of an order. Key order may change unpredictably (but only after insertion or removal of a key). Thus, it's impossible to predict the next key. Python throws the RuntimeError to be safe, and to prevent people from running into unexpected results.
Python 2's dict.items method returns a copy of key-value pairs, so you can safely iterate over it and delete values you don't need by keys, as #wim suggested in comments. Example:
for k, v in my_dict.items():
if v < threshold_value:
del my_dict[k]
However, Python 3's dict.items returns a view object that reflects all changes made to the dictionary. This is the reason the solution above only works in Python 2. You may convert my_dict.items() to list (tuple etc.) to make it Python 3-compatible.
Another way to approach the problem is to select keys you want to delete and then delete them
keys = [k for k, v in my_dict.items() if v < threshold_value]
for x in keys:
del my_dict[x]
This works in both Python 2 and Python 3.
Dictionaries are unordered. By deleting one key nobody can say, what the next key is. So python in general disallow to add or remove keys from a dictionary, over that is iterated.
Just create a new one:
my_dict = {"blue":1,"red":2,"yellow":3,"green":4}
new_dict = {k:v for k,v in my_dict.iteritems() if v >= threshold_value}
I guess that modifying a collection while iterating over it is a hard thing to do to implement properly. Consider following exaple:
>>> list = [1, 2, 3, 4, 5, 6]
>>> for ii in range(len(list)):
print list[ii];
if list[ii] == 3:
del list[ii]
1
2
3
5
6
Notice that in this example 4 was altogether omitted. It is very similat in dictionaries, deleting/adding entries might invalidate internal structures that define order of iteration (for example you deleted enough entries so hash map bucket size changed).
To solve your case --- just create new dictionary and copy items there. As to
This question already has answers here:
How to keep keys/values in same order as declared?
(13 answers)
Closed 9 years ago.
I'm trying to use a dict of key value pairs to store and access lists based on the appropriate keys. Below is what I'm using.
newDict = {'mod':[0,2], 'pro':[2,3], 'st':[6,10]}
newDict2 = {'a':[0,2], 'b':[2,3], 'c':[6,10]}
I'm building this dict in a specific order so I can iterate through it with a for loop. But for whatever reason when I print or put it through a for loop the order of the keys is reordered.
print "the newDict is: " + str(newDict)
print "the newDict2 is: " + str(newDict2)
for key in newDict:
print "the key is: " + str(key)
The output of this is below.
newDict is: {'pro': [2, 3], 'mod': [0, 2], 'st': [6, 10]}
newDict2 is: {'a': [0, 2], 'c': [6, 10], 'b': [2, 3]}
the key is: pro
the key is: mod
the key is: st
I'm more concerned with the order of the keys than the values of the lists. So I don't want to order it by the values of the lists. I've been doing research but can't figure out why it's changing the order. I've tried changing the values in the lists to try and figure it out but I haven't been able to find a pattern. I thought dict's were used when order wasn't a concern. Maybe dicts aren't the way to go about this. Any help is greatly appreciated.
As you mention, python dictionaries do not maintain order. This means that you are not guaranteed to get out the key value pairs in any order when printing the dict or iterating over it after it is created or modified. However, this order, whatever it is, will be maintained as long as no items are inserted or removed.
The lists in your dict, which are values corresponding to keys, are not changing; they still match the keys they were assigned to. However, the order of the key value pairs has changed.
You can use an OrderedDict if you would like the key value pairs to maintain order.
from collections import OrderedDict
newDict = OrderedDict([('mod', [0,2]), ('pro',[2,3]), ('st',[6,10])])
newDict2 = OrderedDict([('a',[0,2]), ('b',[2,3]), ('c',[6,10])])
Sorry for the lag I am having internet problems
from collections import OrderedDict
so that is a special container that is an OrderedDict, it is Ordered by the sequence of key insertion, the keys will maintain their order sequentially.
so you have some process to create the keys,
newDict = OrderedDict()
for some_iterator_value in some_iterator:
key = some_iterator_value
value = we_created_a_list
newDict[key] = value
This question already has answers here:
Removing entries from a dictionary based on values
(4 answers)
Closed 9 years ago.
I know dictionary's are not meant to be used this way, so there is no built in function to help do this, but I need to delete every entry in my dictionary that has a specific value.
so if my dictionary looks like:
'NameofEntry1': '0'
'NameofEntry2': 'DNC'
...
I need to delete(probably pop) all the entries that have value DNC, there are multiple in the dictionary.
Modifying the original dict:
for k,v in your_dict.items():
if v == 'DNC':
del your_dict[k]
or create a new dict using dict comprehension:
your_dict = {k:v for k,v in your_dict.items() if v != 'DNC'}
From the docs on iteritems(),iterkeys() and itervalues():
Using iteritems(), iterkeys() or itervalues() while adding or
deleting entries in the dictionary may raise a RuntimeError or fail
to iterate over all entries.
Same applies to the normal for key in dict: loop.
In Python 3 this is applicable to dict.keys(), dict.values() and dict.items().
You just need to make sure that you aren't modifying the dictionary while you are iterating over it else you would get RuntimeError: dictionary changed size during iteration.
So you need to iterate over a copy of the keys, values (for d use d.items() in 2.x or list(d.items()) in 3.x)
>>> d = {'NameofEntry1': '0', 'NameofEntry2': 'DNC'}
>>> for k,v in d.items():
... if v == 'DNC':
... del d[k]
...
>>> d
{'NameofEntry1': '0'}
This should work:
for key, value in dic.items():
if value == 'DNC':
dic.pop(key)
If restrictions re: modifying the dictionary while iterating on it is a problem, you could create a new class compatible with dict that stores a reverse index of all keys that have the given value (updated at create / update / delete of dict item), which can be arguments to del without iterating over the dict's items.
Subclass dict, and override __setitem__, __delitem__, pop, popitem and clear.
If this is an operation you're doing a lot of, that might be convenient and fast.