我有一个字典列表,格式如下:
dict = [{
"users": {
"user_a": [{
"email": [ "aaa1@email.com", "aaa2@email.com" ]
}],
"user_b": [{
"email": [ "bbb1@email.com" ]
}]
},
"class": "class_A"
},
{
"users": {
"user_d": [{
"email": [ "ddd1@email.com" ]
}],
"user_c": [{
"email": [ "aaa1@email.com", "ccc@email.com" ]
}]
},
"class": "class_B"
}]
我想找到其值包含电子邮件地址“ aaa1@email.com”的键(用户名),因此结果为:
class_A, user_a
class_B, user_c
我正在尝试这种方式:
for key, value in enumerate(dict):
if key =="users":
if value in "aaa1":
但是我从这里迷路了。 如何通过值获取密钥?
非常感谢您的帮助。
答案 0 :(得分:1)
当您执行enumerate(dict)
时,没有得到dict的值,而是告诉python给您列表的值和您所拥有的索引。
因此,您将获得第一个循环:
for index, value in enumerate(my_dict):
print("index is {}".format(index))
print("value is {}".format(value))
>>>index is 0
>>>value is {"users": ... }
所以您需要开始在值的内部查找以获取密钥
value["users"]["user_d"]
正如一些评论所提到的,该结构确实很难使用。如果可以的话,您最好简化一下。如果可以,请删除不必要的图层。
答案 1 :(得分:1)
假设您对当前的数据表示感到困惑,则可以使用flatten_data
from my answer here来避免嵌套问题,这可以将您的数据结构转换成这样的字典:
{(0, 'class'): 'class_A',
(0, 'users', 'user_a', 0, 'email', 0): 'aaa1@email.com',
(0, 'users', 'user_a', 0, 'email', 1): 'aaa2@email.com',
(0, 'users', 'user_b', 0, 'email', 0): 'bbb1@email.com',
(1, 'class'): 'class_B',
(1, 'users', 'user_c', 0, 'email', 0): 'aaa1@email.com',
(1, 'users', 'user_c', 0, 'email', 1): 'ccc@email.com',
(1, 'users', 'user_d', 0, 'email', 0): 'ddd1@email.com'}
这有点容易处理,因为现在您正在处理一个键,该键是一系列索引,您只在乎其中一些,而元素是类或电子邮件。
以下解决方案仅遍及所有字段,仅由于所有其他内容均为电子邮件,因此跳过"class"
。
data = [{'users': {'user_a': [{'email': ['aaa1@email.com', 'aaa2@email.com']}], 'user_b': [{'email': ['bbb1@email.com']}]}, 'class': 'class_A'}, {'users': {'user_d': [{'email': ['ddd1@email.com']}], 'user_c': [{'email': ['aaa1@email.com', 'ccc@email.com']}]}, 'class': 'class_B'}]
# traverse and flatten_data are copied from https://stackoverflow.com/a/36582214/5827215
def traverse(obj, prev_path = "obj", path_repr = "{}[{!r}]".format):
if isinstance(obj,dict):
it = obj.items()
elif isinstance(obj,list):
it = enumerate(obj)
else:
yield prev_path,obj
return
for k,v in it:
yield from traverse(v, path_repr(prev_path,k), path_repr)
def _tuple_concat(tup, idx):
return (*tup, idx)
def flatten_data(obj):
"""converts nested dict and list structure into a flat dictionary with tuple keys
corresponding to the sequence of indices to reach particular element"""
return dict(traverse(obj, (), _tuple_concat))
# !! THIS IS FOR YOU
def extract_groups(flattened_data, matching_email):
for path, elem in flattened_data.items():
# path will have format like (0, 'users', 'user_b', 0, 'email', 0)
# elem is an email address
# skip class mentions, we will retrieve these as needed
if len(path) == 2 and path[1] == "class":
continue
# final element will match the given email?
if elem == matching_email:
# unpack useful elements of path
[cls_idx, _, username, *_] = path
cls = flattened_data[cls_idx, 'class']
yield cls, username
new_data = flatten_data(data)
##import pprint
##pprint.pprint(new_data)
print(*extract_groups(new_data, "aaa1@email.com"), sep="\n")
这确实适用于您的示例输出:
('class_A', 'user_a')
('class_B', 'user_c')
但是任何其他字段都会引起问题,因为它会访问那些认为这是电子邮件的人。因此应将提取函数编写为依赖于数据中一致的结构,使用path[2]
来引用用户ID可能不稳定,但可能存在另一种编写方法,等等。
答案 2 :(得分:1)
您可以使用列表理解:
data = [{'users': {'user_a': [{'email': ['aaa1@email.com', 'aaa2@email.com']}], 'user_b': [{'email': ['bbb1@email.com']}]}, 'class': 'class_A'}, {'users': {'user_d': [{'email': ['ddd1@email.com']}], 'user_c': [{'email': ['aaa1@email.com', 'ccc@email.com']}]}, 'class': 'class_B'}]
email = "aaa1@email.com"
result = [[i['class'], j] for i in data for j, k in i['users'].items() if any(email in x['email'] for x in k)]
输出:
[['class_A', 'user_a'], ['class_B', 'user_c']]
答案 3 :(得分:0)
def get_users_by_email(data, email):
results = []
for record in data:
for user, details in record["users"].items():
emails = details[0]["email"]
if email in emails:
results.append((record["class"], user))
return results
print(get_users_by_email(d, "aaa1@email.com"))
# [('class_A', 'user_a'), ('class_B', 'user_c')]
避免隐藏内置名称:
dict = {...
答案 4 :(得分:0)
您可以尝试以下方法:
for d in dict:
for key in d['users'].keys():
if 'aaa1@email.com' in d['users'][key][0]['email']:
print(d['class'],key)
答案 5 :(得分:0)
尝试
for k, d in dict[0].items():
if str(d).find('aaa1') != -1:
print(k)
但是,另一种选择对您不起作用,但也许对其他人来说是最后的选择
list(dict.keys())[list(dict.values()).index('value')]
在屏幕上打印
print(list(dict.keys())[list(dict.values()).index('value')])