Python list of dictionaries search

后端 未结 21 2069
-上瘾入骨i
-上瘾入骨i 2020-11-22 09:41

Assume I have this:

[
{\"name\": \"Tom\", \"age\": 10},
{\"name\": \"Mark\", \"age\": 5},
{\"name\": \"Pam\", \"age\": 7}
]

and by searchin

相关标签:
21条回答
  • 2020-11-22 09:56

    @Frédéric Hamidi's answer is great. In Python 3.x the syntax for .next() changed slightly. Thus a slight modification:

    >>> dicts = [
         { "name": "Tom", "age": 10 },
         { "name": "Mark", "age": 5 },
         { "name": "Pam", "age": 7 },
         { "name": "Dick", "age": 12 }
     ]
    >>> next(item for item in dicts if item["name"] == "Pam")
    {'age': 7, 'name': 'Pam'}
    

    As mentioned in the comments by @Matt, you can add a default value as such:

    >>> next((item for item in dicts if item["name"] == "Pam"), False)
    {'name': 'Pam', 'age': 7}
    >>> next((item for item in dicts if item["name"] == "Sam"), False)
    False
    >>>
    
    0 讨论(0)
  • 2020-11-22 09:57

    One simple way using list comprehensions is , if l is the list

    l = [
    {"name": "Tom", "age": 10},
    {"name": "Mark", "age": 5},
    {"name": "Pam", "age": 7}
    ]
    

    then

    [d['age'] for d in l if d['name']=='Tom']
    
    0 讨论(0)
  • 2020-11-22 10:00

    You can use a generator expression:

    >>> dicts = [
    ...     { "name": "Tom", "age": 10 },
    ...     { "name": "Mark", "age": 5 },
    ...     { "name": "Pam", "age": 7 },
    ...     { "name": "Dick", "age": 12 }
    ... ]
    
    >>> next(item for item in dicts if item["name"] == "Pam")
    {'age': 7, 'name': 'Pam'}
    

    If you need to handle the item not being there, then you can do what user Matt suggested in his comment and provide a default using a slightly different API:

    next((item for item in dicts if item["name"] == "Pam"), None)
    

    And to find the index of the item, rather than the item itself, you can enumerate() the list:

    next((i for i, item in enumerate(dicts) if item["name"] == "Pam"), None)
    
    0 讨论(0)
  • 2020-11-22 10:00

    Most (if not all) implementations proposed here have two flaws:

    • They assume only one key to be passed for searching, while it may be interesting to have more for complex dict
    • They assume all keys passed for searching exist in the dicts, hence they don't deal correctly with KeyError occuring when it is not.

    An updated proposition:

    def find_first_in_list(objects, **kwargs):
        return next((obj for obj in objects if
                     len(set(obj.keys()).intersection(kwargs.keys())) > 0 and
                     all([obj[k] == v for k, v in kwargs.items() if k in obj.keys()])),
                    None)
    

    Maybe not the most pythonic, but at least a bit more failsafe.

    Usage:

    >>> obj1 = find_first_in_list(list_of_dict, name='Pam', age=7)
    >>> obj2 = find_first_in_list(list_of_dict, name='Pam', age=27)
    >>> obj3 = find_first_in_list(list_of_dict, name='Pam', address='nowhere')
    >>> 
    >>> print(obj1, obj2, obj3)
    {"name": "Pam", "age": 7}, None, {"name": "Pam", "age": 7}
    

    The gist.

    0 讨论(0)
  • 2020-11-22 10:04

    This is a general way of searching a value in a list of dictionaries:

    def search_dictionaries(key, value, list_of_dictionaries):
        return [element for element in list_of_dictionaries if element[key] == value]
    
    0 讨论(0)
  • 2020-11-22 10:04

    My first thought would be that you might want to consider creating a dictionary of these dictionaries ... if, for example, you were going to be searching it more a than small number of times.

    However that might be a premature optimization. What would be wrong with:

    def get_records(key, store=dict()):
        '''Return a list of all records containing name==key from our store
        '''
        assert key is not None
        return [d for d in store if d['name']==key]
    
    0 讨论(0)
提交回复
热议问题