修改嵌套字典



我使用regex查看文件以检查用户名及其操作是否导致错误(error表示错误,INFO表示成功操作)我使用一个嵌套的字典来跟踪操作,用户名作为主键和嵌套的字典有多少INFO和ERROR行他们生成。

#!/usr/bin/env python3
import re
users = {}
with open('logfile.txt') as f:
for line in f:
regex_user = r"(INFO|ERROR): .* ((.+))$"
"""searches for users and if there message was info or error"""
user = re.serach(regex_user, line)
if user is None:
continue
name = user[2]
cat = user[1]
try:
# Method 1?
users[name][cat] = users[name].get(cat, 0) + 1
# Method 2?
users[name][cat] = users.get(name, {}).get(cat, 0) + 1
except KeyError:
print("Where are my keys?")

我想知道这两种方法中的哪一种(如果有的话)正确地修改了字典以增加各自嵌套键的计数。

输出如下所示:

{'John': {'INFO': 22, 'ERROR': 3}}

如果日志中包含22行INFO和3行ERROR,

您可能想用嵌套的collections.defaultdict或使用setdefault()来解决这个问题,尽管在我看来后者不是一个干净的。collections.defaultdict()将允许您引用尚未存在的字典键,这是您的问题的关键。

试试这样写:

import collections
import json
import random
users = collections.defaultdict(lambda: collections.defaultdict(int))
for i in range(100):
user = random.choice(["John", "Jane", "Sanjay"])
cat =  random.choice(["INFO", "ERROR"])
users[user][cat] += 1
print(json.dumps(users, indent=2))

将输出如下内容:

{
"Jane": {
"INFO": 16,
"ERROR": 19
},
"John": {
"ERROR": 21,
"INFO": 10
},
"Sanjay": {
"INFO": 18,
"ERROR": 16
}
}

尽管每次运行都会有所不同。

正如@Ryukashin所指出的,defaultdict()不像dict()那样好地完成print()。因此,如果出于某种原因确实需要的话,倒投是可能的。最简单(但不是最有效)的方式可能是:

users = json.loads(json.dumps(users))

最新更新