简体   繁体   English

在词典列表中查找项目

[英]Find item in a list of dictionaries

I have this data 我有这个数据

data = [
    {
        'id': 'abcd738asdwe',
        'name': 'John',
        'mail': 'test@test.com',
    },
    {
        'id': 'ieow83janx',
        'name': 'Jane',
        'mail': 'test@foobar.com',
    }
]

The id's are unique, it's impossible that multiple dictonaries have the same id. id是唯一的,多个字典都不可能具有相同的id。

For example I want to get the item with the id "ieow83janx". 例如,我想获取ID为“ ieow83janx”的商品。

My current solution looks like this: 我当前的解决方案如下所示:

search_id = 'ieow83janx'
item = [x for x in data if x['id'] == search_id][0]

Do you think that's the be solution or does anyone know an alternative solution? 您认为这是解决方案,还是有人知道替代解决方案?

Since the id s are unique, you can store the items in a dictionary to achieve O(1) lookup. 由于id是唯一的,因此您可以将项目存储在字典中以实现O(1)查找。

lookup = {ele['id']: ele for ele in data}

then you can do 那你就可以

user_info = lookup[user_id]

to retrieve it 找回它

If you are going to get this kind of operations more than once on this particular object, I would recommend to translate it into a dictionary with id as a key. 如果要对该特定对象进行多次此类操作,我建议将其翻译为以id为键的字典。

data = [
    {
        'id': 'abcd738asdwe',
        'name': 'John',
        'mail': 'test@test.com',
    },
    {
        'id': 'ieow83janx',
        'name': 'Jane',
        'mail': 'test@foobar.com',
    }
]

data_dict = {item['id']: item for item in data}
#=> {'ieow83janx': {'mail': 'test@foobar.com', 'id': 'ieow83janx', 'name': 'Jane'}, 'abcd738asdwe': {'mail': 'test@test.com', 'id': 'abcd738asdwe', 'name': 'John'}}

data_dict['ieow83janx']
#=> {'mail': 'test@foobar.com', 'id': 'ieow83janx', 'name': 'Jane'}

In this case, this lookup operation will cost you some constant* O(1) time instead of O(N) . 在这种情况下,此查找操作将花费您一些常量* O(1)时间而不是O(N)

How about the next built-in function ( docs ): next内置函数( docs )如何:

>>> data = [
...     {
...         'id': 'abcd738asdwe',
...         'name': 'John',
...         'mail': 'test@test.com',
...     },
...     {
...         'id': 'ieow83janx',
...         'name': 'Jane',
...         'mail': 'test@foobar.com',
...     }
... ]
>>> search_id = 'ieow83janx'
>>> next(x for x in data if x['id'] == search_id)
{'id': 'ieow83janx', 'name': 'Jane', 'mail': 'test@foobar.com'}

EDIT: 编辑:

It raises StopIteration if no match is found, which is a beautiful way to handle absence: 如果找不到匹配项,它将引发StopIteration ,这是一种处理缺勤的好方法:

>>> search_id = 'does_not_exist'
>>> try:
...     next(x for x in data if x['id'] == search_id)
... except StopIteration:
...     print('Handled absence!')
... 
Handled absence!

Without creating a new dictionary or without writing several lines of code, you can simply use the built-in filter function to get the item lazily, not checking after it finds the match. 无需创建新字典或编写多行代码,您只需使用内置的filter功能就可以延迟获取项目,而无需在找到匹配项后进行检查。

next(filter(lambda d: d['id']==search_id, data))

should for just fine. 应该就好了。

if any(item['id']=='ieow83janx' for item in data):
   #return item

As any function returns true if iterable (List of dictionaries in your case) has value present. 因为任何函数如果可迭代(在您的情况下为字典列表)具有值,则返回true。 While using Generator Expression there will not be need of creating internal List. 使用生成器表达式时,无需创建内部列表。 As there will not be duplicate values for the id in List of dictionaries, any will stop the iteration until the condition returns true. 由于字典列表中的ID不会有重复的值,因此任何值都将停止迭代,直到条件返回true为止。 ie the generator expression with any will stop iterating on shortcircuiting. 即,带有any的生成器表达式将在短路时停止迭代。 Using List comprehension will create a entire List in the memory where as GE creates the element on the fly which will be better if you are having large items as it uses less memory. 使用列表推导会在内存中创建一个完整的列表,因为GE会动态创建元素,如果您有很多物品,这会更好,因为它使用的内存更少。

Would this not achieve your goal? 这不会实现您的目标吗?

for i in data:
    if i.get('id') == 'ieow83janx':
        print(i)
 (xenial)vash@localhost:~/python$ python3.7 split.py {'id': 'ieow83janx', 'name': 'Jane', 'mail': 'test@foobar.com'} 

Using comprehension: 使用理解:

[i for i in data if i.get('id') == 'ieow83janx']

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM