This question already has answers here:
Most Pythonic Way to Build Dictionary From Single List
(2 answers)
Closed 9 years ago.
How do i add key,value to a dictionary in python?
I defined an empty dictionary and now I want to pass a bunch of keys from a list and set their value as 1. From what I did it creates me every iteration a new dictionary, but I want to append the key,value so eventually I will recieve only one dictionary.
this is my code:
def count_d(words):
count_dict={}
words_set= set(words)
for i in words_set:
count_dict[i]= 1
print (count_dict)
What you are looking for is dict.fromkeys along with dict.update.
From the docs
Create a new dictionary with keys from seq and values set to value.
Example Usage
>>> d = {}
>>> d.update(dict.fromkeys(range(10), 1))
>>> d
{0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1}
Note, you need an dict.update along with dict.fromkeys, so as to update the dictionary in-place
Instead, if you want to create a dictionary and assign use the notation
>>> d = dict.fromkeys(range(10), 1)
>>> d
{0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1}
Unfortunately, for in-place update, you need to create a throw-away dictionary before passing to the dict.update method. A non-intuitive method is to leverage itertools
from itertools import izip, repeat
d.update(izip(xrange(10), repeat(1)))
The same idea can be extended to OrderedDict which is often used, as an alternate for OrderedSet as standard library does not provide one.
the fromkeys method does what you want:
count_dict = dict.fromkeys(words_set, 1)
This gives count_dict it's keys from words_set, each with value of 1.
More info on fromkeys here
How do i add key,value to a dictionary in python?
Exactly as you are:
count_dict[i] = 1
From what I did it creates me every iteration a new dictionary
No it doesn't. It keeps appending to the same iteration. The problem is that you print the dictionary-so-far on every iteration.
So, you were very close to what you wanted. I believe that all you want to do is unindent the print statement, so it only happens once at the end, instead of each time through the loop:
def count_d(words):
count_dict={}
words_set= set(words)
for i in words_set:
count_dict[i]= 1
print (count_dict)
Of course it will probably be a lot more useful to return count_dict, not print it. And Abhijit's answer shows a much simpler way to do this. (Another simple way to do it: count_dict = dict(collections.Counter(words_set)). But I think dict.from_keys is more meaningful in this case, despite your variable names.)
But I think this is the part you were actually struggling with.
Related
the output for the code:
dict={k:v for k in range(1,4) for v in range(1,3) }
print(dict)
out put is:
{1: 2, 2: 2, 3: 2}
but thought the output should be:
{1: 1, 2: 1, 3: 1}
why is it taking 2 for the value of v.
Python lets you use the same key multiple times in a dictionary comprehension, but obviously the final dictionary can only contain the key once. The associated value is the last one you specified, as per the Python reference manual, 6.2.7 Dictionary Displays:
When the comprehension is run, the resulting key and value elements are inserted in the new dictionary in the order they are produced.
Is it possible to change the values of multiple keys at once without the loop?
d = {1: 0, 2: 0, 3: 0}
for k in [1,2]:
d[k] += 1
If all you want to do is replace values, then you can use dict.update:
d = {1:0, 2:0, 3:0}
d.update({1:1, 2:1})
# {1: 1, 2: 1, 3: 0}
but as far as I know, there's no way to make a custom change without using a loop of some sort. You could use a list comprehension to make a new dict to feed to .update(), doing it all in one line:
d.update({k: d[k] + 1 for k in [1, 2]})
but I don't think there's a general solution for modifying the dict in-place in this way.
Should be able to use a dictionary's update method, just include the keys you want to update and the values you want them to have.
mydict.update(dict(zip(keys, mytupleValues))))
Brief description of code:
The main code first makes a blank dictionary, which is passed on to my function. The function tallies how many of each number and updates the dictionary which is then returned. However when the function executes, it overwrites the input 'blank_dictionary' to be the same as the dictionary it returns ('new_dictionary'). Why does this happen? I want the 'dictionary' in the main code to remain blank throughout so that it can be reused.
def index_list(lst, blank_dictionary):
new_dictionary = blank_dictionary
for i in lst:
new_dictionary[i] += 1
return new_dictionary
number = 1
maximum = 3
numbers = range(1,maximum+1)
dictionary = {}
for i in numbers:
dictionary[i] = 0
print ('original blank dictionary', dictionary)
new_dictionary = index_list([3,3,3],dictionary)
print ('new dictionary which indexed the list', new_dictionary)
print ('should still be blank, but isnt', dictionary)
Outputs:
original blank dictionary {1: 0, 2: 0, 3: 0}
new dictionary which indexed the list {1: 0, 2: 0, 3: 3}
should still be blank, but isnt {1: 0, 2: 0, 3: 3}
Thanks very much
You are setting new_dictionary to the reference to blank_dictionary. Change the line to new_dictionary = dict(blank_dictionary) and you will be fine. Using the dict() constructor function will make a new new_dictionary and so blank_dictionary will not be modified.
You might want to investigate the defaultdict in the collections module. If you only need to count the number of times each element appears, consider collections.counter.
This behavior is not limited to dicts. In Python, any time you pass a mutable object to a function, the function operates on the original object, not a copy. This is not true for immutable objects like tuples and strings.
However in this case there is no reason to pass a blank dictionary to the function in the first place. The function can create a new dictionary and return it.
So I tried to only allow the program to store only last 3 scores(values) for each key(name) however I experienced a problem of the program only storing the 3 scores and then not updating the last 3 or the program appending more values then it should do.
The code I have so far:
#appends values if a key already exists
while tries < 3:
d.setdefault(name, []).append(scores)
tries = tries + 1
Though I could not fully understand your question, the concept that I derive from it is that, you want to store only the last three scores in the list. That is a simple task.
d.setdefault(name,[]).append(scores)
if len(d[name])>3:
del d[name][0]
This code will check if the length of the list exceeds 3 for every addition. If it exceeds, then the first element (Which is added before the last three elements) is deleted
Use a collections.defaultdict + collections.deque with a max length set to 3:
from collections import deque,defaultdict
d = defaultdict(lambda: deque(maxlen=3))
Then d[name].append(score), if the key does not exist the key/value will be created, if it does exist we will just append.
deleting an element from the start of a list is an inefficient solution.
Demo:
from random import randint
for _ in range(10):
for name in range(4):
d[name].append(randint(1,10))
print(d)
defaultdict(<function <lambda> at 0x7f06432906a8>, {0: deque([9, 1, 1], maxlen=3), 1: deque([5, 5, 8], maxlen=3), 2: deque([5, 1, 3], maxlen=3), 3: deque([10, 6, 10], maxlen=3)})
One good way for keeping the last N items in python is using deque with maxlen N, so in this case you can use defaultdict and deque functions from collections module.
example :
>>> from collections import defaultdict ,deque
>>> l=[1,2,3,4,5]
>>> d=defaultdict()
>>> d['q']=deque(maxlen=3)
>>> for i in l:
... d['q'].append(i)
...
>>> d
defaultdict(<type 'collections.deque'>, {'q': deque([3, 4, 5], maxlen=3)})
A slight variation on another answer in case you want to extend the list in the entry name
d.setdefault(name,[]).extend(scores)
if len(d[name])>3:
del d[name][:-3]
from collections import defaultdict
d = defaultdict(lambda:[])
d[key].append(val)
d[key] = d[key][:3]
len(d[key])>2 or d[key].append(value) # one string solution
Let us consider a dictionary:
sample_dict={1:'r099',2:'g444',3:'t555',4:'f444',5:'h666'}
I want to re-order this dictionary in an order specified by a list containing the order of the dictionary keys that I desire. Let us say the desired order list is:
desired_order_list=[5,2,4,3,1]
So, I want my dictionary to appear like this:
{5:'h666',2:'g444',4:'f444',3:'t555',1:'r099'}
If I can get a list of values that is fine too. Meaning, the result can be this:
['h666','g444','f444','t555','r099']
How do I achieve this in the least complex way possible?
Answer for Python 3.6+
Guido has assured dictionaries would be ordered from Python 3.7 onwards, and they already were as an experimental feature in 3.6. The answer has already been expanded on in Fastest way to sort a python 3.7+ dictionary.
In this case, building a new dict with simple dictionary comprehension based on the items contained in the desired_order_list will do the trick.
sample_dict = {1: 'r099', 2: 'g444', 3: 't555', 4: 'f444', 5: 'h666'}
print(sample_dict)
>>> {1: 'r099', 2: 'g444', 3: 't555', 4: 'f444', 5: 'h666'}
desired_order_list = [5, 2, 4, 3, 1]
reordered_dict = {k: sample_dict[k] for k in desired_order_list}
print(reordered_dict)
>>> {5: 'h666', 2: 'g444', 4: 'f444', 3: 't555', 1: 'r099'}
If you're using an OrderedDict, you can do
for key in [5,2,4,3,1]:
my_ordered_dict[key] = my_ordered_dict.pop(key)
This reinserts everything in your ordered dict in the sequence you want, such that later you can do
my_ordered_dict.values()
And get the list you suggested in the question.
If you wrap the reinsertion in a try: ...; except KeyError: pass, you can reorder an OrderedDict even if not all the keys in your list are present.
Python dictionaries are unordered.
Use OrderedDict instead.
Using an OrderedDict or Eli's solution will probably be a good way to go, but for reference here is a simple way to obtain the list of values you want:
[sample_dict[k] for k in desired_order_list]
If you aren't completely sure that every element from desired_order_list will be a key in sample_dict, use either [sample_dict.get(k) ...] or [... for k in desired_order_list if k in sample_dict]. The first method will put None in for missing keys, the second method will only include values from the keys are are in the dict.
What is the meaning of reordering the dictionary for you? Dictionaries are unordered data structures by their nature - they are used for lookup rather than order.
Do you want to iterate over the dictionary in some specific order? Then just use your desired_order_list:
for key in desired_order_list:
# d is the dictionary
# do stuff with d[key]
As others have mentioned, Python has an OrderedDict (in 2.7 or 3.x), but I don't think it's what you need here. "Reordering" it is just too inefficient. It's much better to just carry your dictionary along with the list of keys in desired order, together.
If you still insist on an OrderedDict, just create a new OrderedDict, inserting the value into it in the order of desired_order_list.
The existing answers more than cover the question except in the special case when the list is incomplete and we want to keep all the values leaving all the rest in the end: Then, after creating the dictionary, update it with the old one to add the missing values:
sample_dict = {1: 'r099', 2: 'g444', 3: 't555', 4: 'f444', 5: 'h666'}
print(reordered_dict)
# {1: 'r099', 2: 'g444', 3: 't555', 4: 'f444', 5: 'h666'}
desired_order_list = [5, 2 ]
reordered_dict = {k: sample_dict[k] for k in desired_order_list}
print(reordered_dict)
# {5: 'h666', 2: 'g444'}
reordered_dict.update(sample_dict)
print(reordered_dict)
# {5: 'h666', 2: 'g444', 1: 'r099', 3: 't555', 4: 'f444'}
wouldn't be easier just doing this way?
sample_dict={1:'r099',2:'g444',3:'t555',4:'f444',5:'h666'}
new_sample_dict={
1: sample_dict[5],
2: sample_dict[2],
3: sample_dict[4],
4: sample_dict[3],
5: sample_dict[1]
}
Use SortedDict provided by django (from django.utils.datastructures import SortedDict). SortedDict stores it's order in keyOrder attribute (which is just a list, so you can reorder it any way you like, anytime).
If you don't have django installed or have no use for django, just lift the implementation django.utils.datatstructures. It doesn't depend on any other parts of django.