Szótárak tömbje; az egyes {kulcs, érték} párok összehasonlítása; és szótárak kombinálása

Megpróbálok optimalizálni egy beágyazott hurkot, amely összehasonlítja a tömb egyik elemét a tömb többi részével .

Két rész van, az első rész például egy tömbnek 3 eleme van, és mindegyik az elem egy szótár:

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

1. iteráció (az 1. elem összehasonlítva a 2. elemmel):

A “someKey tesztkulcsa “két elemnél, mivel a != b, akkor nem csinálunk semmit


2. iteráció (az 1. elem összehasonlítva a 3. elemmel):

A “someKey” tesztkulcsa két elemhez, mivel a == a, logikát csinálunk.


A kód (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 

A kód #Some Logic része megköveteli a kulcsok egyesítését egy szótárból a másikba, például:

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

A kód:

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) 

Minta bemenet (set_of_pk_values):

A minta bemenet alapján tehát azt szeretnénk összehasonlítani, hogy az elődök azonosak-e, ha azonosak, akkor vegyük ezt a kettőt, például:

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

Mivel ugyanazokkal az elődökkel rendelkeznek, ezt a két szótárat egyesítjük a “s” kulcs kivételével: felhasználónév, time_string, setid_hash, setid, condition (ha létezik) ),

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

A második rész nagyon hasonlít az előző példához (3 elem a listán), ugyanabban a szótárban van egy egy kulcshoz társított tömb (most “egy szótár van, két kulccsal a tömb minden elemében), mondjuk”:

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

1. iteráció (az 1. elem összehasonlítva a 2. elemmel):

végighúzza a tömböt a következő kulccsal: someKey_1

b == b (2. elem ” s someKey_2), majd tegyen némi logikát

f != b (2. elem “s someKey_2), nincs logika készítve


2. iteráció (1. elem összehasonlítás s a 3. elemmel):

végighúzza a tömböt a következő kulccsal: someKey_1

b == c (3. elem “s someKey_2), majd csinálj némi logikát

f != c (3. elem “s someKey_2), nincs logika elkészítve


A kód (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 

A kód #Some Logic része megegyezik az első beágyazott hurokkal, amelyhez kulcsok és értékeik egyesítése szükséges egy szótárból a másikba. példa:

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

A kód:

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) 

Hasonlóképpen, amit ennek kellene tennie az előd tömbjének összehasonlítása a setid_hash-szal, ha egyenlőek, akkor kombináljuk.


Teljes kód:

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) 


Jelenleg az első beágyazott hurok futási ideje: 21 másodperc, a második beágyazott hurok pedig körülbelül 19 másodperc. Más, 0–1 másodpercig terjedő folyamatokhoz képest ez a rész egyértelműen szűk keresztmetszetet jelent.

Bárki tudna jó irányba irányítani, hogyan lehet optimalizálni ezt az egyszerű, ámde rendkívül időigényes kódot?


Szerkesztés:

Próbáljon ast.literal_eval elvégezni beágyazott ciklusok előtt:

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 

Válasz

ast.literal_eval(...)

Ha el tudjuk távolítani a látnunk kell, hogy a ciklusok futási ideje szépen csökken. De miért távolíthatjuk el ezt, amit kérdezel? Fontolja meg:

 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 

Amint a fenti kivonatból látható, a ast.literal_eval(...) elemzi és kiértékeli az átadott karakterláncot adja vissza, és adja vissza a karakterlánc szó szerinti ábrázolását (természetesen feltételezve, hogy a karakterlánc érvényes literált képvisel). Nyilvánvaló, hogy hatékonyabb összehasonlítani a m és az n, mint a x és y. Ezenkívül nem tűnik úgy, hogy azzal foglalkozik, hogy val vagy val_2 érvényes python literál, mert a forgatókönyv szerint A ast.literal_eval(...) kivételt dob, alapértelmezés szerint csak a getter(val) és getter(val_2) által visszaadott karakterláncokat hasonlítja össze. . Hosszú történet röviden eltávolíthatja a try: / except: -t, és csak az except záradék alatt található utasításokat használhatja. >

for key in val_2.keys()

A fenti hurok mindkét hurok legbelső hurokjaként fordul elő 1 és 2. Minden egyes iterációnál ellenőrizze, hogy a key nem felel meg-e további 7 lehetséges kulcsértéknek. Ezen kulcsértékek közül 6 fordul elő az Ön által bemutatott adatokban, és a 7. (condition) nem “t”.Hatékonyabbnak kell lennie:

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] 

helyére:

# 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] 

Megjegyzések

  • Van néhány szó szerinti ábrázolásom a húrokról, amelyek a szótár kulcsérték párjában voltak. Ezen gondolkodva írhattam egy for ciklust, amely megpróbálja először megváltoztatni a kulcs, érték pár értéket. Aztán nem kell később ‘ tesztelnem az ast.literal_eval értéket. Ennek jelentős gyorsulása volt, 20 másodperctől milliszekundumig.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük