user3671704 - 1 year ago 56

Python Question

I need to compare a dictionary to values to find all the values that match and add them out. The problem is that I have really large dictionaries and my code is really slow. Is there a better way to do this or to improve my code timing?

`import itertools`

import copy

Dic = {

0: ['-1','A','B','p','r'],

1: ['-','q','p','r'],

2: ['-1','K','q','p','r'],

3: ['+','q','p','r'],

4: ['1','B','q','p','r'],

5: ['-','K','q','p','r'],

}

def S_Sing(SX_Sing,SY_Sing):

if SX_Sing=='+' or SX_Sing=='-':

XX_L=[SX_Sing]

elif SX_Sing!='+' or SX_Sing!='-':

XX_L=SX_Sing

if SY_Sing=='+' or SY_Sing=='-':

YY_L=[SY_Sing]

elif SY_Sing!='+' or SY_Sing!='-':

YY_L=SY_Sing

if XX_L==['+'] or XX_L==['-']:

XX_L.append('1')

if YY_L==['+'] or YY_L==['-']:

YY_L.append('1')

Final=int(''.join(XX_L))+int(''.join(YY_L))

Sum_Final=str(Final)

return Sum_Final

def Comp_Dict_Itself(DicX1):

D_itself_F={}

D_clone= copy.deepcopy(DicX1)

Dic_to_Lista=[]

for k,v in D_clone.iteritems():

Dic_to_Lista.append(v)

for a, b in itertools.combinations(Dic_to_Lista, 2):

if a[:1]!='0' and b[:1]!='0' :

if a[1:]==b[1:]:

S_Final=S_Sing(a[:1],b[:1])

if S_Final==0:

b[:]='0'

a[:]='0'

if S_Final!=0:

b[0]='0'

a[0]=S_Final

somelist_F = [x for x in Dic_to_Lista if x[0]!='0']

for pos, item in enumerate(somelist_F ):

if item[0]!='0':

D_itself_F[pos]= item

return D_itself_F

print(Comp_Dict_Itself(Dic))

Output:

`{0: ['-1', 'A', 'B', 'p', 'r'], 1: ['-2', 'K', 'q', 'p', 'r'], 2: ['1', 'B', 'q', 'p', 'r']}`

What the code does is first check each value, in order to add the values the

`v[1:]`

`v[0]`

`v[0]`

`vA[0]='1'`

`vA[0]='+'`

`vB[0]='-1'`

`vB[0]='-'`

`vA[0]`

`vB[0]`

`0`

`vA[0]=1`

`vB[0]=1`

`vA[0]=2`

`vB[0]=0`

`0`

Answer Source

Okay, I have tried to understand your code and it seems that you are doing the equivalent of the following, which I hope is simpler, clearer and at least a bit more efficient:

```
import itertools as it
def sign_to_num(val):
if val == '+':
return 1
elif val == '-':
return -1
return int(val)
def item_sum(left_val, right_val):
return sign_to_num(left_val) + sign_to_num(right_val)
def comp_dict_itself(d):
values = [list(v) for v in d.values()]
for a, b in it.combinations(values, 2):
if a[0] != '0' != b[0] and a[1:] == b[1:]:
a[0] = str(item_sum(a[0], b[0]))
b[0] = '0'
return dict(enumerate(v for v in values if v[0] != '0'))
```

Notes:

The comparison in your code:

`if a[:1] != '0' and b[:1] != '0'`

is useless because the condition is**always**true. That's because`a`

and`b`

are two`list`

s so`a[:1] == ['0']`

or`a[:1] == ['+']`

. In every case they are different from a`str`

.I have changed that to

`a[0] != '0' and b[0] != '0'`

which can be simplified to`a[0] != '0' != b[0]`

.It doesn't really make sense to have a

`dict`

with integer keys, especially if these keys are consecutive. You could simply use a`list`

.`dict`

s aren't ordered so the list of`values`

need not have the order corresponding to the values of the keys.There's no need to use

`deepcopy`

to first create a new`dict`

and then extract the list of values. See how I build`values`

.