[英]How do you efficiently search across a group of lists in Python?
在 Python 中,我有一組跟蹤有關某些用戶的信息的列表:
user_id = [1,2,3,4,5]
user_name = ['bob', 'alice', 'jerry', 'lisa', 'tom']
user_email = ['bob@email.com', 'alice@email.com', 'jerry@email.com', 'lisa@email.com', 'tom@email.com']
...
其中每個列表中的第 i 個元素相互對應。
我想在給定信息“y”的情況下獲取用戶信息“x”。 在大多數情況下,我會為此使用字典來持續查找時間,但我不想構建和維護幾十個字典。
如果我為上面顯示的每一對列表維護一本字典,我將擁有
name:email
email:name
name:id
id:name
email:id
id:email
它已經開始變得難以管理 - 並且隨着屬性的數量而迅速增長。
我可以將 map 的所有內容都添加到 user_id,然后只有 2n 個字典,但很高興為這個用例學習更合適的數據結構。
為了說明代碼當前是如何實現的:
def get_email_by_user_id(user_id):
return [email for email, uid in zip(user_email, user_id) if uid == user_id][0]
可以想象,非常慢:P
# Dict for holding your data
data = dict()
# Put all your stuff into data
for id, name, email in zip( user_id, user_name , user_email):
data[ id ] = { "id": id , "username" : name , "email" : email }
# Function for lookup up by key and value
def lookup_info( key_name , lookup_value , data ):
'''
Takes a key name, a lookup value and a dictionary of data.
Returns the dictionary item
'''
for k,v in data.items():
if v[ key_name ] == lookup_value:
return( data[ k ] )
由於數據是相關的,因此可以將它們組織成相關列的單個元組列表。
DATA = [
(1, 'bob', 'bob@email.com'),
(2, 'alice', 'alice@email.com'),
(3, 'jerry', 'jerry@email.com'),
(4, 'lisa', 'lisa@email.com'),
(5, 'tom', 'tom@email.com'),
]
然后,可以制作一個僅考慮您感興趣的列的通用 function。
def find_user(user_id=None, user_name=None, user_email=None):
"""Find first user matching given criteria.
A None value means "don't care".
Returns tuple of (id, name, email) if found, otherwise None.
"""
# Collect desired criteria into mapping of record index to desired index value.
criteria_cols = {i: c for (i, c) in enumerate((user_id, user_name, user_email)) if c is not None}
for rec in DATA:
if all(rec[idx] == criteria for (idx, criteria) in criteria_cols.items()):
return rec # return early if found.
這個 function 考慮任何非 None 值,並返回匹配記錄。 如果沒有記錄匹配,則通過並返回默認的 None 值。
print(find_user(user_id=1))
print(find_user(user_id=2))
print(find_user(user_name="alice"))
print(find_user(user_email="jerry@email.com"))
print(find_user(user_id=3, user_email="jerry@email.com"))
print(find_user(user_id=2, user_email="jerry@email.com"))
print(find_user(user_id=3, user_name="jerry"))
結果是
(1, 'bob', 'bob@email.com')
(2, 'alice', 'alice@email.com')
(2, 'alice', 'alice@email.com')
(3, 'jerry', 'jerry@email.com')
(3, 'jerry', 'jerry@email.com')
None
(3, 'jerry', 'jerry@email.com')
最后我選擇了唯一能提供我需要的性能的選項
我決定user_id
的內容是規范標識符。
然后我創建了以下字典:
def make_dictionaries(user_id, other_lists=[('user_name', user_name), ('user_email', user_email)]):
to_id_dictionary = {}
from_id_dictionary = {}
for list_name, list_content in other_lists:
from_id_dictionary[list_name] = {uid:cont for uid,cont in zip(user_id, list_content)}
to_id_dictionary[list_name] = {cont:uid for uid,cont in zip(user_id, list_content)}
return to_id_dictionary, from_id_dictionary
然后我可以這樣做:
def get_email_by_user_name(user_name):
uid = to_id_dictionary['user_name'][user_name] # Get UID from name
return from_id_dictionary[user_email][uid] # Get email from UID
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.