簡體   English   中英

通過匹配字典的值,在列表中查找字典的索引

[英]Find the index of a dict within a list, by matching the dict's value

我有一個字典列表:

list = [{'id':'1234','name':'Jason'},
        {'id':'2345','name':'Tom'},
        {'id':'3456','name':'Art'}]

如何通過匹配 name = 'Tom' 有效地找到索引位置 [0]、[1] 或 [2]?

如果這是一個一維列表,我可以執行 list.index() 但我不確定如何通過搜索列表中的 dicts 值來繼續。

lst = [{'id':'1234','name':'Jason'}, {'id':'2345','name':'Tom'}, {'id':'3456','name':'Art'}]

tom_index = next((index for (index, d) in enumerate(lst) if d["name"] == "Tom"), None)
# 1

如果您需要從名稱中重復獲取,則應按名稱(使用字典)對它們進行索引,這樣獲取操作的時間將是 O(1)。 一個主意:

def build_dict(seq, key):
    return dict((d[key], dict(d, index=index)) for (index, d) in enumerate(seq))

info_by_name = build_dict(lst, key="name")
tom_info = info_by_name.get("Tom")
# {'index': 1, 'id': '2345', 'name': 'Tom'}

一個簡單易讀的版本是

def find(lst, key, value):
    for i, dic in enumerate(lst):
        if dic[key] == value:
            return i
    return -1

它不會有效率,因為您需要遍歷列表檢查其中的每個項目(O(n))。 如果你想要效率,你可以使用dict of dicts 關於這個問題,這里有一種可能的方法來找到它(不過,如果你想堅持這種數據結構,實際上使用生成器更有效,正如 Brent Newey 在評論中所寫的那樣;另見 tokland 的回答):

>>> L = [{'id':'1234','name':'Jason'},
...         {'id':'2345','name':'Tom'},
...         {'id':'3456','name':'Art'}]
>>> [i for i,_ in enumerate(L) if _['name'] == 'Tom'][0]
1

使用過濾器/索引組合似乎最合乎邏輯:

names=[{}, {'name': 'Tom'},{'name': 'Tony'}]
names.index(filter(lambda n: n.get('name') == 'Tom', names)[0])
1

如果您認為可能有多個匹配項:

[names.index(n) for item in filter(lambda n: n.get('name') == 'Tom', names)]
[1]

這是一個查找字典索引位置(如果存在)的函數。

dicts = [{'id':'1234','name':'Jason'},
         {'id':'2345','name':'Tom'},
         {'id':'3456','name':'Art'}]

def find_index(dicts, key, value):
    class Null: pass
    for i, d in enumerate(dicts):
        if d.get(key, Null) == value:
            return i
    else:
        raise ValueError('no dict with the key and value combination found')

print find_index(dicts, 'name', 'Tom')
# 1
find_index(dicts, 'name', 'Ensnare')
# ValueError: no dict with the key and value combination found

@faham 提供的答案是一個很好的單行,但它不會將索引返回到包含該值的字典中。 相反,它返回字典本身。 這是一種簡單的獲取方法:如果有多個索引,則為一個或多個索引列表,如果沒有,則為空列表:

list = [{'id':'1234','name':'Jason'},
        {'id':'2345','name':'Tom'},
        {'id':'3456','name':'Art'}]

[i for i, d in enumerate(list) if 'Tom' in d.values()]

輸出:

>>> [1]

我喜歡這種方法的一點是,通過簡單的編輯,您可以獲得索引和字典作為元組的列表。 這是我需要解決的問題,並找到了這些答案。 在下面,我在不同的字典中添加了一個重復值來展示它是如何工作的:

list = [{'id':'1234','name':'Jason'},
        {'id':'2345','name':'Tom'},
        {'id':'3456','name':'Art'},
        {'id':'4567','name':'Tom'}]

[(i, d) for i, d in enumerate(list) if 'Tom' in d.values()]

輸出:

>>> [(1, {'id': '2345', 'name': 'Tom'}), (3, {'id': '4567', 'name': 'Tom'})]

此解決方案查找在其任何值中包含“Tom”的所有字典。

我需要一個更通用的解決方案來解釋列表中多個字典具有鍵值的可能性,以及使用列表理解的直接實現:

dict_indices = [i for i, d in enumerate(dict_list) if d[dict_key] == key_value] 

一個班輪!?

elm = ([i for i in mylist if i['name'] == 'Tom'] or [None])[0]

以下將返回第一個匹配項的索引:

['Tom' in i['name'] for i in list].index(True)

我的答案最好是一本字典來使用

food_time_dict = {"Lina": 312400, "Tom": 360054, "Den": 245800}
print(list(food_time_dict.keys()).index("Lina"))

我從字典中請求鍵,然后我翻譯列表,如果沒有添加,會出現錯誤,然后我將它用作列表。 但在你的代碼上:

lists = [{'id': '1234', 'name': 'Jason'},
         {'id': '2345', 'name': 'Tom'},
         {'id': '3456', 'name': 'Art'}]
    
    
def dict_in_lists_index(lists, search):  # function for convenience
    j = 0  # [j][i]
    for i in lists:
        try:  # try our varible search if not found in list
            return f"[{j}][{list(i.values()).index(search)}]"
            # small decor
        except ValueError: # error was ValueError
            pass # aa... what must was what you want to do
        j += 1 # not found? ok j++
    return "Not Found"
    
    
def dict_cropped_index(lists, search):
    for i in lists:
        try:
            return list(i.values()).index(search)
        except ValueError:
            pass
    return "Not Found"
    
    
print(dict_in_lists_index(lists, 'Tom')) # and end
print(dict_cropped_index(lists, 'Tom')) # now for sure end

對於給定的可迭代對象, more_itertools.locate生成滿足謂詞的項目的位置。

import more_itertools as mit


iterable = [
    {"id": "1234", "name": "Jason"},
    {"id": "2345", "name": "Tom"},
    {"id": "3456", "name": "Art"}
]

list(mit.locate(iterable, pred=lambda d: d["name"] == "Tom"))
# [1]

more_itertools是一個第三方庫,它在其他有用的工具中實現了itertools 配方

def search(itemID,list):
     return[i for i in list if i.itemID==itemID]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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