我有一個字典串列,如下所示:
[{'user': '123456', 'db': 'db1', 'size': '8628'}
{'user': '123456', 'db': 'db1', 'size': '7168'}
{'user': '123456', 'db': 'db1', 'size': '38160'}
{'user': '222345', 'db': 'db3', 'size': '8628'}
{'user': '222345', 'db': 'db3', 'size': '8628'}
{'user': '222345', 'db': 'db5', 'size': '840'}
{'user': '34521', 'db': 'db6', 'size': '12288'}
{'user': '34521', 'db': 'db6', 'size': '476'}
{'user': '2345156', 'db': 'db7', 'size': '5120'}.....]
此串列包含數百萬個條目。每個用戶可以在多個資料庫中找到,每個用戶可以在同一個資料庫中擁有多個整體。我想總結一下每個用戶每個 db 占用的大小。我不想使用熊貓。目前我這樣做:
- 我創建了 2 個唯一用戶串列和唯一資料庫
- 使用這些串列遍歷大串列并總結 user 和 db 相同的地方
result = []
for user in unique_users:
for db in unique_dbs:
total_size = 0
for i in big_list:
if (i['user'] == user and i['db'] == db):
total_size = float(i['size'])
if(total_size) > 0:
row = {}
row['user'] = user
row['db'] = db
row['size'] = total_size
result.append(row)
問題是這個三重 for 回圈發展成非常大的東西(數千億次迭代),需要永遠總結結果。如果 big_list 很小,則效果很好。
我應該如何處理它以保持快速和簡單?非常感謝!
uj5u.com熱心網友回復:
嘗試將用戶映射到 db 到字典中的總大小。它將需要額外的記憶體,但訪問速度應該更快,并且只需要一次通過資料:
user_to_db_to_size = {}
for entry in unique_users:
user = entry['user']
db = entry['db']
size = int(entry['size'])
if user not in user_to_db_to_size:
user_to_db_to_size[user] = {}
if db not in user_to_db_to_size[user]:
user_to_db_to_size[user][db] = 0
user_to_db_to_size[user][db] = size
print(user_to_db_to_size)
對于您的示例資料,它會產生:
{'123456': {'db1': 53956}, '222345': {'db3': 17256, 'db5': 840}, '34521': {'db6': 12764}, '2345156': {'db7': 5120}}
現在您可以通過以下方式訪問每個用戶/資料庫的總大小:
print(user_to_db_to_size['123456']['db1']) # 53956
uj5u.com熱心網友回復:
當前方法存在兩個主要問題:低效的演算法和低效的資料結構。
首先是使用的演算法顯然效率低下,因為它在大串列上迭代了很多次。不需要遍歷整個串列來過濾唯一用戶和資料庫。您可以遍歷大串列一次并使用字典聚合資料。目標字典的鍵只是一個(user, db)元組。字典的值為total_size。這是一個未經測驗的示例:
# Aggregation part
# Note: a default dict can be used instead to make the code possibly simpler
aggregate_dict = dict()
for i in big_list:
key = (i['user'], i['db'])
value = float(i['size'])
if key in aggregate_dict:
aggregate_dict[key] = value
else:
aggregate_dict[key] = value
# Fast creation of `result`
result = []
for user in unique_users:
for db in unique_dbs:
total_size = aggregate_dict.get((user, key))
if total_size is not None and total_size > 0:
result.append({'user': user, 'db': db, 'size': total_size})
另一個問題是低效的資料結構:對于每一行,復制鍵,而可以使用元組。實際上,更好的資料結構是存盤(column, items)鍵值字典,其中items是目標列的專案串列。這種存盤資料的方式稱為資料幀。這大致是 Pandas 內部使用的(除了它是一個更好的 Numpy 陣列,因為它比大多數操作的串列更緊湊且通常更有效)。對輸入和輸出都使用這種資料結構應該可以顯著提高速度(如果與 Numpy 結合使用)并減少記憶體占用。
uj5u.com熱心網友回復:
你真的應該為此使用熊貓,但如果你不這樣做,你至少可以將你的代碼簡化為對資料的一次傳遞,然后再對結果進行一次傳遞以重新格式化它:
totals = dict()
for d in data:
user = d['user']
u = totals.setdefault(user, {})
db = d['db']
tot = u.setdefault(db, 0)
size = int(d['size'])
u[db] = size
result = []
for user, db in totals.items():
result = [{ 'user' : user, 'db' : name, 'size' : size } for name, size in db.items()]
print(result)
輸出(用于您的樣本資料):
[
{'user': '123456', 'db': 'db1', 'size': 53956},
{'user': '222345', 'db': 'db3', 'size': 17256},
{'user': '222345', 'db': 'db5', 'size': 840},
{'user': '34521', 'db': 'db6', 'size': 12764},
{'user': '2345156', 'db': 'db7', 'size': 5120}
]
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/513595.html
