I have a dictionary full of numbers:
{1:10, 2:5, 3:18, 4:0, 5:1}
All I want to know is, how I could set all these values to zero, without changing each individual element? So it would be like:
{1:0, 2:0, 3:0, 4:0, 5:0}
I'm not used to using dictionaries yet, so any help would be appreciated.
In place:
>>> d = {1:10, 2:5, 3:18, 4:0, 5:1}
>>> for k in d:
... d[k] = 0
...
>>> d
{1: 0, 2: 0, 3: 0, 4: 0, 5: 0}
Comprehension and (optional) reassignment:
>>> d = {1:10, 2:5, 3:18, 4:0, 5:1}
>>> d = {k:0 for k in d}
>>> d
{1: 0, 2: 0, 3: 0, 4: 0, 5: 0}
Another (fairly strange) way to do it:
d = dict.fromkeys(d.keys(), 0)
Using a dictionary comprehension:
>>> d = {1: 10, 2: 5, 3: 18, 4: 0, 5: 1}
>>> d.update({k:0 for k in d})
>>> d
{1: 0, 2: 0, 3: 0, 4: 0, 5: 0}
An even stranger way to do it
>>> d = {1:10, 2:5, 3:18, 4:0, 5:1}
>>> d = d.fromkeys(d, 0)
>>> d
{1: 0, 2: 0, 3: 0, 4: 0, 5: 0}
The advantage this answer has is that it can return an object of the same type as d in the case that d is some mapping other than dict. eg.
>>> from collections import defaultdict
>>> d = defaultdict()
>>> d.update({1:10, 2:5, 3:18, 4:0, 5:1})
>>> d.fromkeys(d, 0)
defaultdict(None, {1: 0, 2: 0, 3: 0, 4: 0, 5: 0})
You can zip the dictionary keys and an iterator of infinite zeros and then create a dictionary like so:
dict(zip(d, itertools.repeat(0))) # create a dict using the zip of the keys and some zeros
Related
I have the following dictionary {44: [0, 1, 0, 3, 6]} and need to convert this to dict1 = {44: {0:0, 1:1, 2:0, 3:3, 4:6}} but my current for loop doesn't work:
maxnumbers = 5 #this is how many values are within the list
for i in list(range(maxnumbers)):
for k in list(dict1.keys()):
for g in dict1[k]:
newdict[i] = g
print(num4)
Can you help me? Thanks in advance.
You can use a dictionary comprehension with enumerate:
d = {44: [0, 1, 0, 3, 6]}
{k:dict(enumerate(v)) for k,v in d.items()}
# {44: {0: 0, 1: 1, 2: 0, 3: 3, 4: 6}}
Use a simple nested dictionary-comprehension that uses enumerate:
d = {44: [0, 1, 0, 3, 6]}
print({k: {i: x for i, x in enumerate(v)} for k, v in d.items()})
# {44: {0: 0, 1: 1, 2: 0, 3: 3, 4: 6}}
a = {44: [0, 1, 0, 3, 6]}
a= {i:{j:a[i][j] for i in a for j in range(len(a[i]))}}
print(a)
output
{44: {0: 0, 1: 1, 2: 0, 3: 3, 4: 6}}
Why your current implementation doesn't work:
for i in list(range(maxnumbers)):
for k in list(dict1.keys()):
for g in dict1[k]:
# this will iterate over all of the values in
# d1[k] and the i: v pair will be overwritten by
# the last value
newdict[i] = g
Taken in steps, this would look like:
# for value in [0, 1, 0, 3, 6]: Just take this set of values as an example
# first, value is 0, and say we are on i = 1, in the outer for loop
newdict[1] = 0
# Then it will progress to value = 1, but i has not changed
# which overwrites the previous value
newdict[1] = 1
# continues until that set of values is complete
In order to fix this, you'll want i and the values of dict1[k] to increment together. This can be accomplished with zip:
for index, value in zip(range(maxnumbers), dict1[k]):
newdict[index] = value
Also, if you need access to both the keys and values, use dict.items():
for k, values in dict1.items():
# then you can use zip on the values
for idx, value in zip(range(maxnumbers), values):
However, the enumerate function already facilitates this:
for k, values in dict1.items():
for idx, value in enumerate(values):
# rest of loop
This is more robust, since you don't have to find what maxnumbers is ahead of time.
To do this in the traditional for loop that you've been using:
new_dict = {}
for k, v in dict1.items():
sub_d = {} # create a new sub_dictionary
for i, x in enumerate(v):
sub_d[i] = x
# assign that new sub_d as an element in new_dict
# when the inner for loop completes
new_dict[k] = sub_d
Or, more compactly:
d = {44: [0, 1, 0, 3, 6]}
new_d = {}
for k, v in d.items():
new_d[k] = dict(enumerate(v))
Where the dict constructor will take an iterable of 2-element tuples as an argument, which enumerate provides
in python, if I want to find the max value of d, but the key only include 1,2,3 other than all the keys in the d. so how to do, thank you.
d = {1: 5, 2: 0, 3: 4, 4: 0, 5: 1}
Just get the keys and values for the keys 1, 2 and 3 in a list of tuples, sort the list and get the first tuple element [0] key [0].
d = {1: 5, 2: 0, 3: 4, 4: 0, 5: 1}
key_max_val = sorted([(k,v) for k,v in d.items() if k in [1,2,3]])[0][0]
print(key_max_val) # Outputs 1
You can use operator:
It will return you the key with maximum value:
In [873]: import operator
In [874]: d = {1: 5, 2: 0, 3: 4, 4: 0, 5: 1}
In [875]: max(d.iteritems(), key=operator.itemgetter(1))[0]
Out[875]: 1
I think this below should work (base on
#Mayank Porwal idea, sorry coz I can not reply):
d = {1: 5, 2: 0, 3: 4, 4: 0, 5: 1}
max(v for k,v in d.items())
Use a generator and the max builtin function:
Max value
max(v for k,v in d.items() if k in [1,2,3])
Max key
max(k for k,v in d.items() if k in [1,2,3])
What would be the most efficient way to get all dict items with value == 3 and create a new dict?
Here is what I have thus far:
d = {1: 2, 2: 2, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1, ...}
new_d = {}
for item in d:
if d[item] == 3:
new_d[item] = d[item]
Is there a more efficient, simpler way to do this? Perhaps using a map?
You could use a dict comprehension:
new_d = {k:v for k, v in d.items() if v == 3}
Note that you should call d.iteritems() in Python 2.x to avoid creating an unnecessary list.
As you can see from the timeit.timeit tests below, this solution is more efficient:
>>> from timeit import timeit
>>> d = {1: 2, 2: 2, 3: 1, 4: 1, 5: 1, 6: 1, 7: 1, 8: 1}
>>>
>>> timeit('''
... new_d = {}
... for item in d:
... if d[item] == 1:
... new_d[item] = d[item]
... ''', 'from __main__ import d')
5.002458692375711
>>>
>>> timeit('new_d = {k:v for k, v in d.items() if v == 1}', 'from __main__ import d')
4.844044424640543
>>>
It is also a lot simpler, which is always good.
For a list like this:
for i in range(100):
things.append({'count':1})
for i in range(100):
things.append({'count':2})
To count the number of 1 in list:
len([i['count'] for i in things if i['count'] == 1])
What is a better way?
collections.Counter
>>> from collections import Counter
>>> c = Counter([thing['count'] for thing in things])
>>> c[1] # Number of elements with count==1
100
>>> c[2] # Number of elements with count==2
100
>>> c.most_common() # Most common elements
[(1, 100), (2, 100)]
>>> sum(c.values()) # Number of elements
200
>>> list(c) # List of unique counts
[1, 2]
>>> dict(c) # Converted to a dict
{1: 100, 2: 100}
Perhaps you could do something like this?
class DictCounter(object):
def __init__(self, list_of_ds):
for k,v in list_of_ds[0].items():
self.__dict__[k] = collections.Counter([d[k] for d in list_of_ds])
>>> new_things = [{'test': 1, 'count': 1} for i in range(10)]
>>> for i in new_things[0:5]: i['count']=2
>>> d = DictCounter(new_things)
>>> d.count
Counter({1: 5, 2: 5})
>>> d.test
Counter({1: 10})
Extended DictCounter to handle missing keys:
>>> class DictCounter(object):
def __init__(self, list_of_ds):
keys = set(itertools.chain(*(i.keys() for i in list_of_ds)))
for k in keys:
self.__dict__[k] = collections.Counter([d.get(k) for d in list_of_ds])
>>> a = [{'test': 5, 'count': 4}, {'test': 3, 'other': 5}, {'test':3}, {'test':5}]
>>> d = DictCounter(a)
>>> d.test
Counter({3: 2, 5: 2})
>>> d.count
Counter({None: 3, 4: 1})
>>> d.other
Counter({None: 3, 5: 1})
I have 2 lists:
correct_list = [1,2,3,4,5,6,7,8,9,10]
other_list = [4,5,6,7,8,10]
I would like to combine these two lists so:
combined_list = [{k:1, v:0},{k:2, v:0},{k:3, v:0}, {k:4, v:4}, {etc}]
so basically am saying that the key is the correct list, and where ever the other_list does not match the correct_list, fill in a 0, or " " . And of they do match, fill in the matching value
Does this makes sense ?
How would I do this in python ?
[{'k': c, 'v': c if c in other_list else 0} for c in correct_list]
By the way, if the only elements of the dictionaries are k and v, consider building a dictionary instead of a list of dictionaries:
>>> dict((c, c if c in other_list else 0) for c in correct_list)
{1: 0, 2: 0, 3: 0, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 0, 10: 10}