Is there a more correct way to do the following:
if a in dic.keys():
dic[a] += 1
else:
dic[a] = 1
I.e. to increment values corresponding to keys in a dictionary, when those keys may not be present.
Use dict.get:
dic[a] = dic.get(a, 0) + 1
You can use a defaultdict to provide a default value for keys not present in the dictionary.
>>> d = defaultdict(int)
>>> d[1] += 1
>>> d[1]
1
>>> d[5]
0
You could use collections.Counter()
dic = collections.Counter()
dic['a'] += 1
dic['b'] # will be zero
See http://docs.python.org/2/library/collections.html#collections.Counter
you can use dict.setdefault():
In [12]: dic=dict(zip(('a','b'),[0]*2))
In [13]: dic
Out[13]: {'a': 0, 'b': 0}
In [14]: dic['c']=dic.setdefault('c',0)+1
In [15]: dic
Out[15]: {'a': 0, 'b': 0, 'c': 1}
In [16]: dic['a']=dic.setdefault('a',0)+1
In [17]: dic
Out[17]: {'a': 1, 'b': 0, 'c': 1}
using a loop:
In [18]: dic=dict(zip(('a','b'),[0]*2))
In [19]: for x in ('a','b','c','a'):
....: dic[x]=dic.setdefault(x,0)+1
....:
In [20]: dic
Out[20]: {'a': 2, 'b': 1, 'c': 1}
Related
I want to convert a list to a default dictionary to have a default value of 0 in case the key doesn't have any value (from the list).
list : order = ['a',1,'b',2,'c']
what I did using ZIP :
it = iter(order)
res_dict = dict(zip(it,it))
print(res_dict)
but it excludes c as a key, as the list doesn't have the next index after c.
Result I got : {'a': 1, 'b': 2}
Result i want : {'a': 1, 'b': 2, 'c': 0}
You might want to consider using itertools and .zip_longest().
For example:
import itertools
l = ['a',1,'b',2,'c']
d = dict(itertools.zip_longest(l[::2], l[1::2], fillvalue=0))
print(d)
Output:
{'a': 1, 'b': 2, 'c': 0}
This is working:
d = dict()
for i in range(len(order)):
if i%2==0 and i+1<len(order):
d[order[i]] =order[i+1]
elif i+2>(len(order)):
d[order[i]]=0
Result:
{'a': 1, 'b': 2, 'c': 0}
To solve the problem of two consequent keys you can use a custom function to split the list
def splitdefault(o):
i = 0
while i < len(o):
# there is a next element to check
if i + 1 < len(o):
# the next element is int
if isinstance(o[i + 1], int):
yield o[i], o[i + 1]
i += 2
else:
yield o[i], 0
i += 1
# i is the last element
else:
yield o[i], 0
i += 1
order = ["a", 1, "b", 2, "c", "d", 3, "e"]
for g in splitdefault(order):
print(g)
res_dict = dict(splitdefault(order))
print(res_dict)
Which produces
{'a': 1, 'b': 2, 'c': 0, 'd': 3, 'e': 0}
Cheers!
How can I iterate over only X number of dictionary items? I can do it using the following bulky way, but I am sure Python allows a more elegant way.
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
x = 0
for key in d:
if x == 3:
break
print key
x += 1
If you want a random sample of X values from a dictionary you can use random.sample on the dictionary's keys:
from random import sample
d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
X = 3
for key in sample(d, X):
print key, d[key]
And get output for example:
e 5
c 3
b 2
I have two lists:
L1 = ['A','B','A','C','A']
L2 = [1, 4, 6, 1, 3]
I want to create a dictionary which has the following output:
DictOutSum = {'A':10, 'B':4, 'C':1}
DictOutCount = {'A':3, 'B':1, 'C':1}
i.e. Lists L1 and L2 both have same number of elements and the elements in them corresponds one to one. I want to find sum of all numbers in L2 for each unique element in L1 and make a dictionary out of it(DictOutSum). I also want to create another dictionary which stores the counts of number of unique elements of L1(DictOutCount).
I don't even have an idea where to start for this other than to use a for loop.
Pure python implementation:
>>> dict_sum = dict.fromkeys(L1, 0)
>>> dict_count = dict.fromkeys(L1, 0)
>>> for k,n in zip(L1, L2):
... dict_sum[k] += n
... dict_count[k] += 1
...
>>> dict_sum
{'A': 10, 'B': 4, 'C': 1}
>>> dict_count
{'A': 3, 'B': 1, 'C': 1}
Fancy one-liner implementations:
>>> from collections import Counter
>>> Counter(L1) # dict_count
Counter({'A': 3, 'B': 1, 'C': 1})
>>> sum((Counter({k:v}) for k,v in zip(L1, L2)), Counter()) # dict_sum
Counter({'A': 10, 'B': 4, 'C': 1})
You should use the zip builtin function
import collections
DictOutSum = collections.defaultdict(int)
DictOutCount = collections.defaultdict(int)
for l1, l2 in zip(L1, L2):
DictOutSum[l1] += l2
DictOutCount[l1] += 1
>>> L1 = ['A','B','A','C','A']
>>> L2 = [1, 4, 6, 1, 3]
>>>
>>> DictOutCount = {v:0 for v in L1}
>>> DictOutSum = {v:0 for v in L1}
>>> for v1,v2 in zip(L1,L2):
... DictOutCount[v1] += 1
... DictOutSum[v1] += v2
...
>>>
>>> DictOutCount
{'A': 3, 'C': 1, 'B': 1}
>>> DictOutSum
{'A': 10, 'C': 1, 'B': 4}
>>>
The mega elementary way
L1 = ['A','B','A','C','A']
L2 = [1, 4, 6, 1, 3]
# Carries the information
myDict = {}
# Build the dictionary
for x in range(0,len(L1)):
# Initialize the dictionary IF the key doesn't exist
if L1[x] not in myDict:
myDict[L1[x]] = {}
myDict[L1[x]]['sum'] = 0
myDict[L1[x]]['count'] = 0
# Collect the information you need
myDict[L1[x]][x] = L2[x]
myDict[L1[x]]['sum'] += L2[x]
myDict[L1[x]]['count'] += 1
# Build the other two dictionaries
DictOutSum = {}
DictOutCount = {}
# Literally feed the data
for element in myDict:
DictOutSum[element] = myDict[element]['sum']
DictOutCount[element] = myDict[element]['count']
print DictOutSum
# {'A': 10, 'C': 1, 'B': 4}
print DictOutCount
# {'A': 3, 'C': 1, 'B': 1}
Side note: From your username, are you Persian?
DictOutCount, use collections.Counter,
import collections
DictOutCount = collections.Counter(L1)
print(DictOutCount)
Counter({'A': 3, 'C': 1, 'B': 1})
DictOutSum,
DictOutSum = dict()
for k, v in zip(L1, L2):
DictOutSum[k] = DictOutSum.get(k, 0) + v
print(DictOutSum)
# Output
{'A': 10, 'C': 1, 'B': 4}
Previous answer, DictOutSum,
import itertools
import operator
import functools
DictOutSum = dict()
for name, group in itertools.groupby(sorted(itertools.izip(L1, L2)), operator.itemgetter(0)):
DictOutSum[name] = functools.reduce(operator.add, map(operator.itemgetter(1), group))
print(DictOutSum)
{'A': 10, 'C': 1, 'B': 4}
The main steps are:
use itertools.izip to make an iterator that aggregates elements from each of L1 and L2
use itertools.groupby to make an iterator that returns consecutive keys and groups from the iterable (sorting before that)
use functools.reduce for cumulatively addition
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have around 1000 of dictionary like this.
x = {'a':1, 'b': 2, 'c':5}
y = {'b':10, 'c': 11}
z = {'e':5, 'b': 2}
I want a merged dictionary like this.
f = {'a':[1,0,0], 'b': [2,10,2], 'c':[5,11,0], 'e':[0,0,5]}
Is there a iterative way to do this.? After creating the final dictionary i want to create a matrix where a , b, c, e will be the column heading with three rows as shown below:
a b c e
1 2 5 0
0 10 11 0
0 2 0 5
keys = ('a', 'b', 'c', 'e')
dicts = (x, y, z)
f = {k: [d.get(k, 0) for d in dicts] for k in keys}
Or as a one-liner:
f = {k: [d.get(k, 0) for d in (x, y, z)] for k in ('a', 'b', 'c', 'e')}
You can get your keys with dict.viewkeys and a reduce function, then use collections.defaultdict to append the corresponding values to keys :
>>> x = {'a':1, 'b': 2, 'c':5}
>>> y = {'b':10, 'c': 11}
>>> z = {'e':5, 'b': 2}
>>> l=[x,y,z]
>>> keys=reduce(lambda i,j: i | j ,[j.viewkeys() for j in l])
>>> from collections import defaultdict
>>> d=defaultdict(list)
>>> for k in keys :
... for i in l:
... d[k].append(i.get(k,0))
...
>>> d
defaultdict(<type 'list'>, {'a': [1, 0, 0], 'c': [5, 11, 0], 'b': [2, 10, 2], 'e': [0, 0, 5]})
Then you can create the proper matrix :
>>> [[i]+j for i,j in d.items()]
[['a', 1, 0, 0], ['c', 5, 11, 0], ['b', 2, 10, 2], ['e', 0, 0, 5]]
Here's how to perform the two tasks:
from collections import defaultdict
dicts = [{'a':1, 'b': 2, 'c':5},
{'b':10, 'c': 11},
{'e':5, 'b': 2}]
# determine what keys exist in the dictionaries and sort them
keys = sorted(reduce(lambda a,b: a|b, (set(d) for d in dicts)))
f = defaultdict(list)
for k in keys:
for d in dicts:
f[k].append(d.get(k, 0))
print 'merged\n f: {}'.format(dict(f))
matrix = [keys] + [[d.get(k, 0) for k in keys] for d in dicts]
print '\nmatrix:'
for row in matrix:
print ' '.join('{:>2}'.format(elem) for elem in row)
Output:
merged
f: {'a': [1, 0, 0], 'c': [5, 11, 0], 'b': [2, 10, 2], 'e': [0, 0, 5]}
matrix:
a b c e
1 2 5 0
0 10 11 0
0 2 0 5
I am looking for a Pythonic way (the less code possible) to unite the content of two dictionnaries :
basket1 = {"ham":2,"eggs":3}
basket2 = {"eggs":4,"spam":1}
I want to get a third basket that is going to be the "sum" of the two other, basket 3 should be:
basket3 --> {"ham":2,"eggs":7,"spam":1}
If possible, doing this using set
I'd use a Counter, which is a kind of defaultdict with some nice properties:
>>> from collections import Counter
>>> basket1 = {"ham":2,"eggs":3}
>>> basket2 = {"eggs":4,"spam":1}
>>> basket_sum = Counter(basket1) + Counter(basket2)
>>> basket_sum
Counter({'eggs': 7, 'ham': 2, 'spam': 1})
which you could convert back into a pure dict if you wanted:
>>> dict(basket_sum)
{'eggs': 7, 'ham': 2, 'spam': 1}
Since you're trying to count the values, use collections.Counter:
basket3 = collections.Counter(basket1)
basket3.update(basket2)
Or:
basket3 = collections.Counter(basket1) + collections.Counter(basket2)
In [2]: basket1 = {"ham":2,"eggs":3}
In [3]: basket2 = {"eggs":4,"spam":1}
In [4]: baskets = [basket1, basket2]
In [5]: answer = collections.defaultdict(int)
In [6]: for basket in baskets:
...: for item in basket:
...: answer[item] += basket[item]
...:
In [7]: answer
Out[7]: defaultdict(<type 'int'>, {'eggs': 7, 'ham': 2, 'spam': 1})
In [8]: dict(answer)
Out[8]: {'eggs': 7, 'ham': 2, 'spam': 1}