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

Python

Python Problem Overview


I have a list of dicts:

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

How can I efficiently find the index position [0],[1], or [2] by matching on name = 'Tom'?

If this were a one-dimensional list I could do list.index() but I'm not sure how to proceed by searching the values of the dicts within the list.

Python Solutions


Solution 1 - Python

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

If you need to fetch repeatedly from name, you should index them by name (using a dictionary), this way get operations would be O(1) time. An idea:

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

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

Solution 2 - Python

A simple readable version is

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

Solution 3 - Python

It won't be efficient, as you need to walk the list checking every item in it (O(n)). If you want efficiency, you can use dict of dicts. On the question, here's one possible way to find it (though, if you want to stick to this data structure, it's actually more efficient to use a generator as Brent Newey has written in the comments; see also tokland's answer):

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

Solution 4 - Python

Seems most logical to use a filter/index combo:

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

And if you think there could be multiple matches:

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

Solution 5 - Python

Answer offered by @faham is a nice one-liner, but it doesn't return the index to the dictionary containing the value. Instead it returns the dictionary itself. Here is a simple way to get: A list of indexes one or more if there are more than one, or an empty list if there are none:

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()]

Output:

>>> [1]

What I like about this approach is that with a simple edit you can get a list of both the indexes and the dictionaries as tuples. This is the problem I needed to solve and found these answers. In the following, I added a duplicate value in a different dictionary to show how it works:

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()]

Output:

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

This solution finds all dictionaries containing 'Tom' in any of their values.

Solution 6 - Python

Here's a function that finds the dictionary's index position if it exists.

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

Solution 7 - Python

I needed a more general solution to account for the possibility of multiple dictionaries in the list having the key value, and a straightforward implementation using list comprehension:

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

Solution 8 - Python

One liner!?

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

Solution 9 - Python

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

Solution 10 - Python

The following will return the index for the first matching item:

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

Solution 11 - Python

my answer is better in one a dictionary to use

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

I request keys from the dictionary, then I translate the list if it is not added, there will be an error then I use it as a list. but on your code:

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

Solution 12 - Python

For a given iterable, more_itertools.locate yields positions of items that satisfy a predicate.

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 is a third-party library that implements itertools recipes among other useful tools.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionensnareView Question on Stackoverflow
Solution 1 - PythontoklandView Answer on Stackoverflow
Solution 2 - PythonEmileView Answer on Stackoverflow
Solution 3 - PythonaeterView Answer on Stackoverflow
Solution 4 - Pythonmichael salmonView Answer on Stackoverflow
Solution 5 - PythonstanelyView Answer on Stackoverflow
Solution 6 - PythonmartineauView Answer on Stackoverflow
Solution 7 - PythonSebastian TimarView Answer on Stackoverflow
Solution 8 - PythonfahamView Answer on Stackoverflow
Solution 9 - PythonRohan KumaraView Answer on Stackoverflow
Solution 10 - PythonDan BoschenView Answer on Stackoverflow
Solution 11 - PythonAIRC.GroupView Answer on Stackoverflow
Solution 12 - PythonpylangView Answer on Stackoverflow