Let's say I have a python dictionary {apple: 15, orange: 22, juice: 7, blueberry:19} and I want to reorder the dictionary according to the order of this list [juice, orange, blueberry, apple]. How would I do this cleanly/efficiently?
Note: the list could very well have more items than the dictionary.
O(n) method is to simply loop over your list of ordered keys:
{k: d[k] for k in keys}
If you want to maintain the same mutable reference to the dictionary (for whatever reason), just delete the key and add it in a loop. It will naturally order itself correctly.
As mentioned in the comments, dictionaries don't have an order in Python. Assuming you want to get the dictionary values in the same order as the list, you could do something like this. It checks to see if the key is in the dictionary first, so extra items in the list won't matter
d = {apple: 15, orange: 22, juice: 7, blueberry:19}
order = [juice, orange, blueberry, apple]
for key in order:
if key in d:
print(d[key])
Alternatively as #ewong mentioned, you can use an OrderedDict, which tracks the order a key is added. It seems like to re-order one you have to create a new OrderedDict, so in your case you could potentially create one from your original dictionary.
from collections import OrderedDict
ordered_d = OrderedDict([(key, d[key]) for key in order if key in d])
Related
I am trying to find the missed dictionary element by comparing two dictionary list
list1=[{"amount":"1000",'dept':'marketing',"desig":"mgr",'id':'101'},
{"amount":"1331",'dept':None,"desig":"accnt",'id':'102'},{"amount":"1351",'dept':'mark',"desig":"sales",'id':'103'}]
list2=[{"amount":"1500",'dept':None,"desig":"mgr2",'id':'101'},
{"amount":"1451",'dept':'IT',"desig":"accnt",'id':'102'}]
difference=[item for item in list1 if item["id"] not in list2]
but its not giving the expected output for the missed key
expected output:
missed={"amount":"1351",'dept':'mark',"desig":"sales",'id':'103'}
Your edited question requires matching against the 'id' key, not the entire dictionary object as before. Since that is hashable, it is simplest to put it in a set to efficiently test whether something is part of the collection or not. (Edit: Credit #KellyBundy for suggesting set comprehension)
id_set = {item['id'] for item in list2}
difference = [item for item in list1 if item['id'] not in id_set]
difference here gives a list of all missing dictionaries. So to access all of them, you need to iterate over it.
for missed in difference:
print(f'{missed=}')
and the output will be (it will print one line per dictionary)
missed={'amount': '1351', 'dept': 'mark', 'desig': 'sales', 'id': '103'}
If you know there will only be one missing item, or you only need the first element, you can use difference[0] to directly access the dictionary.
The following is my list
List_data = [{'cases_covers': 0.1625}, {'headphone': 0.1988}, {'laptop': 0.2271}, {'mobile': 0.2501}, {'perfume': 0.4981}, {'shoe': 0.1896}, {'sunglass': 0.1693}]
Final answer should be like this:
[{'perfume': 0.4981}, {'mobile': 0.2501}, {'laptop': 0.2271}, {'headphone': 0.1988},{'shoe': 0.1896}, {'sunglass': 0.1693},{'cases_covers': 0.1625}]
i want them to be sorted based on the value of the key in descending order
You can get the list of values of a dictionary d with d.values(). Since your dictionaries have only one entry each, these lists will be singletons. You can use these singleton-lists to sort List_data by supplying a keyword argument to the sort function.
Please note that in your example, "perfume", "mobile", "laptop" are the keys and 0.4981, 0.2501 are the values, according to the standard vocabulary for dictionaries in python.
List_data = [{'cases_covers': 0.1625}, {'headphone': 0.1988}, {'laptop': 0.2271}, {'mobile': 0.2501}, {'perfume': 0.4981}, {'shoe': 0.1896}, {'sunglass': 0.1693}]
List_data.sort(key=lambda d: list(d.values()), reverse=True)
print(List_data)
Output:
[{'perfume': 0.4981}, {'mobile': 0.2501}, {'laptop': 0.2271}, {'headphone': 0.1988}, {'shoe': 0.1896}, {'sunglass': 0.1693}, {'cases_covers': 0.1625}]
Important remark
The previous piece of code was answering your question literally, without knowledge of the context in which you are trying to sort this list of dictionaries.
I am under the impression that your use of lists and dictionaries is not optimal. Of course, without knowledge of the context, I am only guessing. But perhaps using only one dictionary would better suit your needs:
dictionary_data = {'cases_covers': 0.1625, 'headphone': 0.1988, 'laptop': 0.2271, 'mobile': 0.2501, 'perfume': 0.4981, 'shoe': 0.1896, 'sunglass': 0.1693}
list_data = sorted(dictionary_data.items(), key=lambda it: it[1], reverse=True)
print(list_data)
Output:
[('perfume', 0.4981), ('mobile', 0.2501), ('laptop', 0.2271), ('headphone', 0.1988), ('shoe', 0.1896), ('sunglass', 0.1693), ('cases_covers', 0.1625)]
Suppose ,I have a dictionary
key={'a':5}
Now ,I want to add values to it cumulatively without overwriting the current value but adding on to it.How to do it?
I am giving an instance:
for post in doc['post']:
if 'wow' in post:
value=2
for reactor in post['wow']['reactors']:
dict_of_reactor_ids.update({reactor['img_id']:value})
if 'sad' in post:
value=2
for reactor in post['sad']['reactors']:
dict_of_reactor_ids.update({reactor['img_id']:value})
Suppose if the dictionary is like this in first iteration
dict_of_reactor_ids={101:2,102:1}
and NOW I want to increase the value of 101 key by 3 ,then how to do that.
dict_of_reactor_ids={101:5,102:1}
Now in second iteration of post ,I want to add values to the current values in dictionary without overwriting the current value.
I have tried update method but I think it just updates the whole value instead of adding onto it.
Sounds like a typical case of Counter:
>>> from collections import Counter
>>> c = Counter()
>>> c["a"] += 1 # works even though "a" is not yet present
>>> c.update({"a": 2, "b": 2}) # possible to do multiple updates
{"a": 3, "b": 2}
In your case the benefit is that it works even when the key is not already in there (default value is 0), and it allows updates of multiple values at once, whereas update on a normal dict would overwrite the value as you've noticed.
You can also use defaultdict, it "defaults" when there is not yet an existing key-value pair and you still use the cumulative add +=:
from collections import defaultdict
dict_of_reactor_ids = defaultdict(int)
dict_of_reactor_ids[101] += 2
dict_of_reactor_ids[102] += 1
dict_of_reactor_ids['101'] += 3
print(dict_of_reactor_ids['101'])
5
This is currently my code.
if Pokémon == 'Charmander':
selectyourmove = input('Select your move: Flamethrower, Fire Fang,
Scratch or Ember: ')#select your move
if selectyourmove == 'Flamethrower':
numberchoosing1 = random.randint(20, 22)#randomly decides
damage of the chosen move in the range
print(choice, 'has lost' ,numberchoosing1, 'health out of its'
,HP, 'health!')
My dictionary is quite simple. It is:
HP = {'Char':'60', 'Squir':'50', 'Pika':'80', 'Eve':'50', 'Bulb':'70', 'Clef':'100'}
Also all these have been defined.
How do I get a value that was randomly chosen from a dictionary
The 1st way is to use dict.popitem:
Remove and return an arbitrary (key, value) pair from the dictionary.
popitem() is useful to destructively iterate over a dictionary, as often used in set algorithms. If the dictionary is empty, calling popitem() raises a KeyError.
Note, that this method randomness actually comes from implementation of hashing algorithm and python dict elements layout. That's more obscurity than randomness.
The 2nd way, the truely 'random', is using the random.choice. It doesn't modify the dict, as chooses random index in the list supplied to it:
import random
hp = {'Char':'60', 'Squir':'50', 'Pika':'80', 'Eve':'50', 'Bulb':'70', 'Clef':'100'}
print(random.choice(list(hp.keys())))
Illustration of working principle:
>>> random.choice(list(HP.keys()))
'Pika'
>>> random.choice(list(HP.keys()))
'Clef'
>>> random.choice(list(HP.keys()))
'Pika'
The list is constructed here from .keys(), but when you need pairs (like from popitem()) you could use .items():
>>> random.choice(list(HP.items()))
('Clef', '100')
>>> random.choice(list(HP.items()))
('Pika', '80')
>>> random.choice(list(HP.items()))
('Char', '60')
The same way, of course the .values() will work producing only right-hand elements of dict items though, thus won't give you much satisfaction unlike .keys() or .items() does.
PS: Then if you need the reproduce prev. run, you can fix the 'randomness' with random.seed
That depends on what you mean by "value". A dictionary is a set of key,value pairs, so technically the values of your dictionary are just the strings '50', '60', '50', '100', '70', '80', and the keys are the strings 'Eve', 'Char', 'Squir', 'Clef', 'Bulb', 'Pika'.
You can these collections by using HP.keys() and HP.values(), and you can use list() to cast these collections to lists. Then, you can use random.choice to get a random value.
So to get a random key from your dictionary (which it seems like is what you actually want), you could do:
import random
keys = HP.keys()
key_list = list(keys)
choice = random.choice(key_list)
Or, more concisely:
import random
choice = random.choice(list(HP.keys()))
Then you can get the associated value for that key with HP[choice]
list_color=['Red','Blue','Green']
for i ,b in enumerate(list_color,1):
if i<=2:
dict ={b:i}
else:
break
i+=1
print(dict)
Output:
{'Green':3}
You told interpreter to reassign name dict with new value, not to update a dict.
dict = {b:i} # we talk about this line
For creating objects based on another iterable, comprehensions are typical way to go, in this case a dictionary comprehension:
colors = ['Red','Blue','Green']
d = {color: idx for idx, color in enumerate(colors, 1)}
# {'Blue': 2, 'Green': 3, 'Red': 1}
Order is not kept, because dictionaries are unordered data structure.
Also, try to avoid naming your objects based on builtins, when dict name is used, it shadows dict builtin function.
I'm not sure why you have so many statements in the for loop, so I'm giving a simple example:
list_color=['Red','Blue','Green']
dict={}
for i ,b in enumerate(list_color,1):
dict[b] = i
print(dict)
Please note, how I define dict to be an empty dictionary before the loop. The other thing I changed is the way you assign values to the dictionary. You were overwriting the complete content of the dictionary with each assignment. I'm showing now how to add values to the dictionary.
I recommend a site like http://www.pythontutor.com/visualize.html which allows to to visualize the execution of the code. Then you can see what's going on/wrong/not according to your expectations.