簡體   English   中英

如何有效地搜索 Python 中的一組列表?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM