En række ordbøger; sammenligning af hvert {nøgle, værdi} par og kombinere ordbøger

Jeg prøver at optimere et indlejret til sløjfer, der sammenligner et element i arrayet med resten af elementet i arrayet .

Der er to dele, den første del er for eksempel, en Array har 3 elementer, og hver element er en ordbog:

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

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

Testnøgle til “someKey “for to elementer, da a != b, så gør vi intet


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

Testnøgle til “someKey” for to elementer, da a == a, gør vi noget logisk


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 af koden kræver kombination af nøgler fra en ordbog til en anden, 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) 

Eksempelindgang (set_of_pk_values):

Så baseret på prøveindgangen, skal vi sammenligne, hvis forgængere er de samme, hvis de er de samme, lad os tage 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"} 

Da de har de samme forgængere, kombinerer vi disse to ordbøger undtagen nøglen “s: brugernavn, tidsstreng, setid_hash, setid, tilstand (hvis der findes ),

 {"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"} 

Anden del svarer meget til det foregående eksempel (3 emner på listen), i samme ordbog har vi en array tilknyttet en nøgle (nu er der en enkelt ordbog med to nøgler i hvert element i arrayet), lad os sige:

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

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

sløjfer gennem arrayet med nøglen: someKey_1

b == b (2. element ” s someKey_2), lav derefter logik

f != b (2. element “s someKey_2), der er ingen logik udført


2nd iteration (1. element sammenlign s med 3. element):

sløjfer gennem arrayet med nøglen: someKey_1

b == c (3. element “s someKey_2), derefter gør noget logik

f != c (3. element “s someKey_2), ingen logik er udført


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 af koden er den samme som den første indlejrede løkke, som kræver kombination af nøgler og deres værdier fra en ordbog til en anden, 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) 

Ligeledes hvad dette skal gøre er sammenligne arrayet af forgængeren med setid_hash, hvis de er ens, så kombinerer vi dem.


Fuld 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) 


I øjeblikket er køretiden for den første nestede loop: 21 sekunder, og den anden nestede loop er omkring 19 sekunder. Sammenlignet med andre processer, der spænder fra 0-1 sekunder, er denne del helt klart en flaskehals.

Kan nogen pege mig i den rigtige retning om, hvordan man optimerer dette stykke enkel, men alligevel ekstremt tidskrævende kode?


Rediger:

Prøv at lave en ast.literal_eval før indlejrede sløjfer:

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 dine opkald til ast.literal_eval(...) vi burde se en god reduktion i løbtiden for dine sløjfer. Men hvorfor kan vi fjerne dette, spørger du? Overvej:

 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 uddraget ovenfor, ast.literal_eval(...) analyserer og evaluerer den streng, du sender det, og returner en bogstavelig gengivelse af den streng (forudsat selvfølgelig, at strengen repræsenterer en gyldig bogstavelig). Det er klart, at det er mere effektivt at sammenligne m og n end det er at sammenligne x og y. Det ser ikke ud til, at du er bekymret for, om val eller val_2 er en gyldig python-bogstavelig, fordi under scenariet ast.literal_eval(...) kaster en undtagelse, du vælger som standard bare at sammenligne strengene returneret af getter(val) og getter(val_2) Lang historie kort, du kan fjerne try: / except: og bare bruge de udsagn, du har under except -klausulen.

for key in val_2.keys()

Ovenstående sløjfe opstår som den indre sløjfe af begge sløjfer 1 og 2. Ved hver iteration kontrollerer du, at key ikke svarer til 7 andre mulige nøgleværdier. 6 af disse nøgleværdier forekommer i de data, du har præsenteret, og den 7. (condition) ikke “t.Det bør være mere effektivt at 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 bogstavelig gengivelse af strenge, der var inde i nøgleværdiparet i ordbogen. Når jeg tænkte over det, var jeg i stand til at skrive en for-loop, der forsøger at ændre nøgleværdiparet først. Så behøver jeg ikke ‘ at teste for ast.literal_eval senere. Dette fik betydelig hastighed, fra 20 sekunder til millisekunder.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *