Python two dictionaries in dictionary, increase value in specific key - python

I want to increase value in dictionary of a dictionary, there is a major dictionary 'a' which has two separate dictionaries: 'be' and 'ce'. I want to increase value of specific key, determined by variables like 'dist' and 'bec' but I cannot reach the key of one of the minor dictionaries:
import collections
from collections import defaultdict
a={}
be = {}
ce = {}
for z in range(1,11):
be["b_{0}".format(z)] = 0
be = collections.OrderedDict(sorted(be.items()))
for c in range(1,11):
for b in range(1,11):
ce["c_{0}_{1}".format(c,b)]= 0
ce = collections.OrderedDict(sorted(ce.items()))
for x in range(1,10):
a["a_{0}".format(x)] = be,ce
a = collections.OrderedDict(sorted(a.items()))
dist = 3
bec = 10
a["a_"+str(dist)]["b_"+str(bec)] += 1
I tried to print "a["a_"+str(dist)]["b_"+str(bec)]" but it didnt work, it only works when I print only "a["a_"+str(dist)]"

Here's the simplest possible approach:
>>> from collections import Counter
>>> a = Counter()
>>> a[(3, 'b', 10)] += 1
>>> a[(3, 'b', 10)] += 1
>>> a[(3, 'b', 10)]
2
>>> a[(3, 'b', 8)]
0
Is there any way in which this doesn't work?

Related

how to print a string showing the number of times each character is repeated in a string?

Given a string S, how to print a string containing number of times the character is repeated?
for example:
input: aaabbbbccaa
output: a3b4c2a2
my approach:
s = input()
len_string = ''
cur_char = s[0]
cur_counter = 0
for i in range(len(s)):
if s[i] == cur_char:
cur_counter += 1
if s[i] != cur_char or i == len(s) - 1:
len_string += cur_char + str(cur_counter)
cur_char = s[i]
cur_counter = 1
print(len_string)
Because you have shared your code, here is one concise way using groupby:
from itertools import groupby
s = 'aaabbbbccaa'
print(''.join([k + str(len(list(g))) for k, g in groupby(s)]))
# a3b4c2a2
I would use collections.Counter https://docs.python.org/2/library/collections.html#counter-objects
Init signature: collections.Counter(*args, **kwds)
Docstring:
Dict subclass for counting hashable items. Sometimes called a bag
or multiset. Elements are stored as dictionary keys and their counts
are stored as dictionary values.
>>> c = Counter('abcdeabcdabcaba') # count elements from a string
>>> c.most_common(3) # three most common elements
[('a', 5), ('b', 4), ('c', 3)]
>>> sorted(c) # list all unique elements
['a', 'b', 'c', 'd', 'e']
>>> ''.join(sorted(c.elements())) # list elements with repetitions
'aaaaabbbbcccdde'
>>> sum(c.values()) # total of all counts
15
>>> c['a'] # count of letter 'a'
5
>>> for elem in 'shazam': # update counts from an iterable
... c[elem] += 1 # by adding 1 to each element's count
>>> c['a'] # now there are seven 'a'
7
>>> del c['b'] # remove all 'b'
>>> c['b'] # now there are zero 'b'
0
>>> d = Counter('simsalabim') # make another counter
>>> c.update(d) # add in the second counter
>>> c['a'] # now there are nine 'a'
9
>>> c.clear() # empty the counter
>>> c
Counter()
Note: If a count is set to zero or reduced to zero, it will remain
in the counter until the entry is deleted or the counter is cleared:
>>> c = Counter('aaabbc')
>>> c['b'] -= 2 # reduce the count of 'b' by two
>>> c.most_common() # 'b' is still in, but its count is zero
[('a', 3), ('c', 1), ('b', 0)]
I think there is a way to do this much more easy:
x='aaabbbbccaa'
noreplist = list(dict.fromkeys(x))
countstring=''
for i in noreplist:
z=z+i+str(x.count(i))
print(countstring)
First, you have x that is your string.
Then you make a list with every char from that string, but without repeating any char.
And last, just counts how many times is that char repeated on the original string, and concatenate in a 'count string'.
#y is a list that contains every character in the string
#z is a list parallel to y but it contains the number of times each element in list y #has
x=input("Input string: ")
y=[]
z=[]
acc=0
for i in range(len(x)):
if(x[i] not in y):
y.append(x[i])
for i in range(len(y)):
for j in range(len(x)):
if(y[i]==x[j]):
acc=acc+1
z.append(acc)
acc=0
for k in range(len(y)):
print(str(y[k])+str(z[k]))

Add bi-grams to a pandas dataframe

I have a list of bi-grams like this:
[['a','b'],['e', ''f']]
Now I want to add these bigrams to a DataFrame with their frequencies like this:
b f
a|1 0
e|0 1
I tried doing this with the following code, but this raises an error, because the index doesn't exist yet. Is there a fast way to do this for really big data? (like 200000 bigrams)
matrixA = pd.DataFrame()
# Put the counts in a matrix
for elem in grams:
tag1, tag2 = elem[0], elem[1]
matrixA.loc[tag1, tag2] += 1
from collections import Counter
bigrams = [[['a','b'],['e', 'f']], [['a','b'],['e', 'g']]]
pairs = []
for bg in bigrams:
pairs.append((bg[0][0], bg[0][1]))
pairs.append((bg[1][0], bg[1][1]))
c = Counter(pairs)
>>> pd.Series(c).unstack() # optional: .fillna(0)
b f g
a 2 NaN NaN
e NaN 1 1
The above is for the intuition. This can be wrapped up in a one line generator expression as follows:
pd.Series(Counter((bg[i][0], bg[i][1]) for bg in bigrams for i in range(2))).unstack()
You can use Counter from the collections package. Note that I changed the contents of the list to be tuples rather than lists. This is because Counter keys (like dict keys) must be hashable.
from collections import Counter
l = [('a','b'),('e', 'f')]
index, cols = zip(*l)
df = pd.DataFrame(0, index=index, columns=cols)
c = Counter(l)
for (i, c), count in c.items():
df.loc[i, c] = count

Finding the minimum value for different variables

If i am doing some math functions for different variables for example:
a = x - y
b = x**2 - y**2
c = (x-y)**2
d = x + y
How can i find the minimum value out of all the variables. For example:
a = 4
b = 7
c = 3
d = 10
So the minimum value is 3 for c. How can i let my program do this.
What have i thought so far:
make a list
append a,b,c,d in the list
sort the list
print list[0] as it will be the smallest value.
The problem is if i append a,b,c,d to a list i have to do something like:
lst.append((a,b,c,d))
This makes the list to be -
[(4,7,3,10)]
making all the values relating to one index only ( lst[0] )
If possible is there any substitute to do this or any way possible as to how can i find the minimum!
LNG - PYTHON
Thank you
You can find the index of the smallest item like this
>>> L = [4,7,3,10]
>>> min(range(len(L)), key=L.__getitem__)
2
Now you know the index, you can get the actual item too. eg: L[2]
Another way which finds the answer in the form(index, item)
>>> min(enumerate(L), key=lambda x:x[1])
(2, 3)
I think you may be going the wrong way to solving your problem, but it's possible to pull values of variable from the local namespace if you know their names. eg.
>>> a = 4
>>> b = 7
>>> c = 3
>>> d = 10
>>> min(enumerate(['a', 'b', 'c', 'd']), key=lambda x, ns=locals(): ns[x[1]])
(2, 'c')
a better way is to use a dict, so you are not filling your working namespace with these "junk" variables
>>> D = {}
>>> D['a'] = 4
>>> D['b'] = 7
>>> D['c'] = 3
>>> D['d'] = 10
>>> min(D, key=D.get)
'c'
>>> min(D.items(), key=lambda x:x[1])
('c', 3)
You can see that when the correct data structure is used, the amount of code required is much less.
If you store the numbers in an list you can use a reduce having a O(n) complexity due the list is not sorted.
numbers = [999, 1111, 222, -1111]
minimum = reduce(lambda mn, candidate: candidate if candidate < mn else mn, numbers[1:], numbers[0])
pack as dictionary, find min value and then find keys that have matching values (possibly more than one minimum)
D = dict(a = 4, b = 7, c = 3, d = 10)
min_val = min(D.values())
for k,v in D.items():
if v == min_val: print(k)
The buiit-in function min will do the trick. In your example, min(a,b,c,d) will yield 3.

using FOR statement on 2 elements at once python

I have the following list of variables and a mastervariable
a = (1,5,7)
b = (1,3,5)
c = (2,2,2)
d = (5,2,8)
e = (5,5,8)
mastervariable = (3,2,5)
I'm trying to check if 2 elements in each variable exist in the master variable, such that the above would show B (3,5) and D (5,2) as being elements with at least 2 elements matching in the mastervariable. Also note that using sets would result in C showing up as matchign but I don't want to count C cause only 'one' of the elements in C are in mastervariable (i.e. 2 only shows up once in mastervariable not twice)
I currently have the very inefficient:
if current_variable[0]==mastervariable[0]:
if current_variable[1] = mastervariable[1]:
True
elif current_variable[2] = mastervariable[1]:
True
#### I don't use OR here because I need to know which variables match.
elif current_variable[1] == mastervariable[0]: ##<-- I'm now checking 2nd element
etc. etc.
I then continue to iterate like the above by checking each one at a time which is extremely inefficient. I did the above because using a FOR statement resulted in me checking the first element twice which was incorrect:
For i in a:
for j in a:
### this checked if 1 was in the master variable and not 1,5 or 1,7
Is there a way to use 2 FOR statement that allows me to check 2 elements in a list at once while skipping any element that has been used already? Alternatively, can you suggest an efficient way to do what I'm trying?
Edit: Mastervariable can have duplicates in it.
For the case where matching elements can be duplicated so that set breaks, use Counter as a multiset - the duplicates between a and master are found by:
count_a = Counter(a)
count_master = Counter(master)
count_both = count_a + count_master
dups = Counter({e : min((count_a[e], count_master[e])) for e in count_a if count_both[e] > count_a[e]})
The logic is reasonably intuitive: if there's more of an item in the combined count of a and master, then it is duplicated, and the multiplicity is however many of that item are in whichever of a and master has less of them.
It gives a Counter of all the duplicates, where the count is their multiplicity. If you want it back as a tuple, you can do tuple(dups.elements()):
>>> a
(2, 2, 2)
>>> master
(1, 2, 2)
>>> dups = Counter({e : min((count_a[e], count_master[e])) for e in count_a if count_both[e] > count_a[e]})
>>> tuple(dups.elements())
(2, 2)
Seems like a good job for sets. Edit: sets aren't suitable since mastervariable can contain duplicates. Here is a version using Counters.
>>> a = (1,5,7)
>>>
>>> b = (1,3,5)
>>>
>>> c = (2,2,2)
>>>
>>> d = (5,2,8)
>>>
>>> e = (5,5,8)
>>> D=dict(a=a, b=b, c=c, d=d, e=e)
>>>
>>> from collections import Counter
>>> mastervariable = (5,5,3)
>>> mvc = Counter(mastervariable)
>>> for k,v in D.items():
... vc = Counter(v)
... if sum(min(count, vc[item]) for item, count in mvc.items())==2:
... print k
...
b
e

Most elegant way to count integers in a list

I am looking for the most elegant way to do the following:
Let's say that I want to count number of times each integer appears in a list; I could do it this way:
x = [1,2,3,2,4,1,2,5,7,2]
dicto = {}
for num in x:
try:
dicto[num] = dicto[num] + 1
except KeyError:
dicto[num] = 1
However, I think that
try:
dicto[num] = dicto[num] + 1
except KeyError:
dicto[num] = 1
is not the most elegant ways to do it; I think that I saw the above code replaced by a single line. What is the most elegant way to do this?
I realized that this might be a repeat, but I looked around and couldn't find what I was looking for.
Thank You in advance.
Use the Counter class
>>> from collections import Counter
>>> x = [1,2,3,2,4,1,2,5,7,2]
>>> c = Counter(x)
Now you can use the Counter object c as dictionary.
>>> c[1]
2
>>> c[10]
0
(This works for non-existant values too)
>>> from collections import defaultdict
>>> x = [1,2,3,2,4,1,2,5,7,2]
>>> d = defaultdict(int)
>>> for i in x:
d[i] += 1
>>> dict(d)
{1: 2, 2: 4, 3: 1, 4: 1, 5: 1, 7: 1}
Or just collections.Counter, if you are on Python 2.7+.
Bucket sort, as you're doing, is entirely algorithmically appropriate (discussion). This seems ideal when you don't need the additional overhead from Counter:
from collections import defaultdict
wdict = defaultdict(int)
for word in words:
wdict[word] += 1

Categories