En rekke ordbøker; sammenligne hvert {nøkkel, verdi} par; og kombinere ordbøker

Jeg prøver å optimalisere et nestet for løkker som sammenligner et element i matrisen med resten av elementet i matrisen .

Det er to deler, den første delen er for eksempel, en matrise har 3 elementer, og hver element er en ordbok:

[{"someKey_1":"a"}, {"someKey_1":"b"}, {"somekey_1":"a"}] 

1. iterasjon (1. element sammenlignes med 2. element):

Testnøkkel til «someKey «for to elementer, siden a != b, så gjør vi ingenting


2. iterasjon (1. element sammenlignes med 3. element):

Testnøkkel til «someKey» for to elementer, siden a == a, gjør vi litt logikk


Koden (Sudo):

for idx, first_dictionary in enumerate(set_of_pk_values): for second_dictionary in (set_of_pk_values[idx+1:]): if (first_dictionary["someKey"] == second_dictionary["someKey"]): #Some Logic 

#Some Logic-delen av koden krever kombinasjon av nøkler fra en ordbok til en annen, for eksempel:

for key in val_2.keys(): val[key]=val_2[key] 

Koden:

newList = [] skipList = [] checked = [] getter = itemgetter("predecessor") getter_2 = itemgetter("setid_hash") for idx, val in enumerate(set_of_pk_values): if(idx not in skipList): for val_2 in set_of_pk_values[idx+1:]: if(idx not in checked): try: if (ast.literal_eval(getter(val)) == ast.literal_eval(getter(val_2))): for key in val_2.keys(): if(key != "block" and key != "username" and key != "setid" and key != "setid_hash" and key != "predecessor" and key != "time_string" and key != "condition"): val[key]=val_2[key] skipList.append(idx) except: if (getter(val) == getter(val_2)): for key in val_2.keys(): if(key != "block" and key != "username" and key != "setid" and key != "setid_hash" and key != "predecessor" and key != "time_string" and key != "condition"): val[key]=val_2[key] skipList.append(idx) checked.append(idx) 

Eksempelinngang (set_of_pk_values):

Så basert på prøveinngangen, er det vi ønsker å sammenligne hvis forgjengerne er de samme, hvis de er de samme, la oss ta disse to som for eksempel:

{"username": u"radcad", "predecessor": u"[u"6a5e4bc9a328c1aeb52c565b675e6141", u"818428a59215e75d76111c8ca29a314d", u"6c acfc059508f8cb716ad0126f001f84"]", "time_string": u"2014/06/26@07:02:40", "S.clpe_leafcell.UTC_Post_start": u"1403766190", "setid_hash": u"14443f7238927d6e95 befbe12ecc6dd0", "setid": u"1986068", "block": u"simple_buff"} {"username": u"radcad", "predecessor": u"[u"6a5e4bc9a328c1aeb52c565b675e6141", u"818428a59215e75d76111c8ca29a314d", u"6c acfc059508f8cb716ad0126f001f84"]", "S.rcxt_maxcl.Predecessors": u"clpe_leafcell", "time_string": u"2015/03/08@03:06:26", "setid_hash": u"ffce9f0c46f3459acbba4f0ced884f3a", "setid": u"3095862", "block": u"simple_buff"} 

Siden de har de samme forgjengerne, vil vi kombinere disse to ordbøkene bortsett fra nøkkelen «s: brukernavn, tidsstreng, setid_hash, setid, tilstand (hvis eksisterer ),

 {"username": u"radcad", "predecessor": u"[u"6a5e4bc9a328c1aeb52c565b675e6141", u"818428a59215e75d76111c8ca29a314d", u"6c acfc059508f8cb716ad0126f001f84"]", "time_string": u"2014/06/26@07:02:40", "S.clpe_leafcell.UTC_Post_start": u"1403766190", "S.rcxt_maxcl.Predecessors": u"clpe_leafcell", "setid_hash": u"14443f7238927d6e95 befbe12ecc6dd0", "setid": u"1986068", "block": u"simple_buff"} 

Den andre delen er veldig lik forrige eksempel (3 elementer i listen), i samme ordbok har vi en array assosiert med en nøkkel (nå er det en enkelt ordbok med to nøkler i hvert element i matrisen), la oss si:

[{"someKey_1":[b,f]}{"someKey_2":a}, {"someKey_1":[e,f]}{"someKey_2":b}, {"somekey_1":[h,k]}{"someKey_2":c}] 

1. iterasjon (1. element sammenlignes med 2. element):

sløyfer gjennom matrisen med nøkkelen: someKey_1

b == b (2. element » s someKey_2), gjør så litt logikk

f != b (2. element «s someKey_2), ingen logikk er gjort


2nd iterasjon (1. element sammenlign s med tredje element):

sløyfer gjennom matrisen med nøkkelen: someKey_1

b == c (3. element «s someKey_2), deretter gjøre noe logikk

f != c (3. element er noen Key__2), ingen logikk er gjort


Koden (Sudo):

for idx, val in enumerate(set_of_pk_values): for idx_2, val_2 in enumerate(set_of_pk_values): for pred in val["someKey_1"]: if(val_2["someKey_2"] == pred): #Some Logic 

#Some Logic-delen av koden er den samme som den første nestede sløyfen, som krever kombinasjon av nøkler og deres verdier fra en ordbok til en annen, for eksempel:

for key in val_2.keys(): val[key]=val_2[key] 

Koden:

newList = [] skipList = [] checked = [] getter = itemgetter("predecessor") getter_2 = itemgetter("setid_hash") for idx, val in enumerate(set_of_pk_values): if(idx not in skipList): for idx_2, val_2 in enumerate(set_of_pk_values): if(idx != idx_2): try: for pred in ast.literal_eval(getter(val)): if(getter_2(val_2) == pred): for key in val_2.keys(): if(key != "block" and key != "username" and key != "setid" and key != "setid_hash" and key != "predecessor" and key != "time_string" and key != "condition"): val[key]=val_2[key] skipList.append(idx_2) except: for pred in getter(val): if(getter_2(val_2) == pred): for key in val_2.keys(): if(key != "block" and key != "username" and key != "setid" and key != "setid_hash" and key != "predecessor" and key != "time_string" and key != "condition"): val[key]=val_2[key] skipList.append(idx_2) 

Tilsvarende hva dette skal gjøre er sammenligne matrisen til forgjengeren med setid_hash, hvis de er like, så kombinerer vi.


Full kode:

def test(): set_of_pk_values = [] cache = chartCache.objects.get(username_chartNum="Test 3_leimax", openedConfig="chartTable_774164170") data = chartCache_Data.objects.filter(ID = cache) max_value = data.aggregate(Max("counter"))["counter__max"] if(max_value != None): if(max_value != 0): cached = True for i in xrange(0, max_value+1): newItem = {} set_of_pk_values.append(newItem) for items in data.iterator(): set_of_pk_values[items.counter][str(items.key)] = items.value newList = [] skipList = [] checked = [] getter = itemgetter("predecessor") getter_2 = itemgetter("setid_hash") print str(len(set_of_pk_values)) timeNow = datetime.datetime.now() ############################################## #First Nested For Loop ############################################## for idx, val in enumerate(set_of_pk_values): if(idx not in skipList): for val_2 in set_of_pk_values[idx+1:]: if(idx not in checked): try: if (ast.literal_eval(getter(val)) == ast.literal_eval(getter(val_2))): for key in val_2.keys(): if(key != "block" and key != "username" and key != "setid" and key != "setid_hash" and key != "predecessor" and key != "time_string" and key != "condition"): val[key]=val_2[key] skipList.append(idx) except: if (getter(val) == getter(val_2)): for key in val_2.keys(): if(key != "block" and key != "username" and key != "setid" and key != "setid_hash" and key != "predecessor" and key != "time_string" and key != "condition"): val[key]=val_2[key] skipList.append(idx) checked.append(idx) ############################################## #Second Nested For Loop ############################################## for idx, val in enumerate(set_of_pk_values): if(idx not in skipList): for idx_2, val_2 in enumerate(set_of_pk_values): if(idx != idx_2): try: for pred in ast.literal_eval(getter(val)): if(getter_2(val_2) == pred): for key in val_2.keys(): if(key != "block" and key != "username" and key != "setid" and key != "setid_hash" and key != "predecessor" and key != "time_string" and key != "condition"): val[key]=val_2[key] skipList.append(idx_2) except: for pred in getter(val): if(getter_2(val_2) == pred): for key in val_2.keys(): if(key != "block" and key != "username" and key != "setid" and key != "setid_hash" and key != "predecessor" and key != "time_string" and key != "condition"): val[key]=val_2[key] skipList.append(idx_2) for idx, val in enumerate(set_of_pk_values): if(idx not in skipList): newList.append(val) set_of_pk_values = newList print str(len(set_of_pk_values)) timeEnd = datetime.datetime.now() print str(timeEnd - timeNow) 


For tiden er kjøretiden for den første nestede sløyfen: 21 sekunder, og den andre nestede sløyfen er rundt 19 sekunder. Sammenlignet med andre prosesser, som strekker seg fra 0-1 sekunder, er denne delen helt klart en flaskehals.

Kan noen peke meg i riktig retning for hvordan du kan optimalisere dette stykke enkel, men ekstremt tidkrevende kode? / p>


Rediger:

Prøv å gjøre en ast.literal_eval før nestede looper:

for items in set_of_pk_values: for key in item.keys(): getter = itemgetter(key) try: toChange = ast.literal_eval(getter(items)) items[key] = toChange except: pass 

Svar

ast.literal_eval(...)

Hvis vi kan fjerne samtalene dine til ast.literal_eval(...) vi bør se en fin reduksjon i kjøretiden til løkkene dine. Men hvorfor kan vi fjerne dette spør du? Tenk:

 m = "[0, 1, 2, ... , 9,999]" # a str representation of list w/ 10k elements, 0-9999 n = "[0, 1, 2]" x = ast.literal.eval(m) y = ast.literal.eval(n) x == range(10000) # true 

Som du kan se fra kodebiten ovenfor, ast.literal_eval(...) vil analysere og evaluere hvilken streng du passerer den, og returner en bokstavelig representasjon av den strengen (forutsatt selvfølgelig at strengen representerer en gyldig bokstavelig). Det er tydelig at det er mer effektivt å sammenligne m og n enn å sammenligne x og y. Det ser heller ikke ut til at du er opptatt av om val eller val_2 er en gyldig python-bokstavelig, fordi under scenariet ast.literal_eval(...) kaster et unntak, du bruker som standard bare å sammenligne strengene som returneres av getter(val) og getter(val_2) . Lang historie kort, du kan fjerne try: / except: og bare bruke utsagnene du har under except klausulen.

for key in val_2.keys()

Ovennevnte sløyfe oppstår som den innerste sløyfen til begge sløyfer 1 og 2. For hver iterasjon sjekker du at key ikke tilsvarer 7 andre mulige nøkkelverdier. 6 av disse nøkkelverdiene forekommer i dataene du har presentert, og den 7. (condition) ikke «t.Det bør være mer effektivt å erstatte:

for key in val_2.keys(): if(key != "block" and key != "username" and key != "setid" and key != "setid_hash" and key != "predecessor" and key != "time_string" and key != "condition"): val[key]=val_2[key] 

med:

# put this at the top of the test function x_keys = set(["block", "username", "setid", "setid_hash", "predecessor", "time_string", "condition"]) # ... for key in set(val_2.keys()) - x_keys: val[key] = val_2[key] 

Kommentarer

  • Jeg har en bokstavelig fremstilling av strenger som var inne i nøkkelverdiparet i ordboken. Tenker på det, var jeg i stand til å skrive en for loop som prøver å endre nøkkelen, verdiparet først. Da trenger jeg ikke ‘ å teste for ast.literal_eval senere. Dette hadde betydelig fart, fra 20 sekunder til millisekunder.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *