Python 将dict的元组键转换为新的dict

Python 将dict的元组键转换为新的dict,python,dictionary,tuples,Python,Dictionary,Tuples,我有这样一句话: { ('America', 25, 'm', 'IT'): 10000, ('America', 22, 'm', 'IT'): 8999, ('Japan', 24, 'f', 'IT'): 9999, ('Japan', 23, 'f', 'IT'): 9000 } 现在,在这个例子中,我想用键'America','m','IT'得到所有结果。在上述情况下,这将是: {25: 10000, 22: 8999} 我目前的解决方案如下

我有这样一句话:

{
    ('America', 25, 'm', 'IT'): 10000,
    ('America', 22, 'm', 'IT'): 8999,
    ('Japan',   24, 'f', 'IT'): 9999,
    ('Japan',   23, 'f', 'IT'): 9000
}
现在,在这个例子中,我想用键'America','m','IT'得到所有结果。在上述情况下,这将是:

{25: 10000, 22: 8999}
我目前的解决方案如下:

res = dict()
for key, cnt in stats.items():
    country, age, sex, job = key
    try:
        res[(country, sex, job)][age] = cnt
    except KeyError as e:
        res[(country, sex, job)] = {}
        res[(country, sex, job)][age] = cnt

print res['America', 'm', 'IT']

我有更好的方法吗?因为这段代码似乎不那么简单。

您可以使用dict理解来完成这项工作:

>>> data = {
...     ('America', 25, 'm', 'IT'): 10000,
...     ('America', 22, 'm', 'IT'): 8999,
...     ('Japan',   24, 'f', 'IT'): 9999,
...     ('Japan',   23, 'f', 'IT'): 9000
... }
>>> {x: value for (w, x, y, z), value in data.items() if w == "America" and y == "m" and z == "IT"}
{25: 10000, 22: 8999}

您可以使用听写理解来执行此操作:

>>> data = {
...     ('America', 25, 'm', 'IT'): 10000,
...     ('America', 22, 'm', 'IT'): 8999,
...     ('Japan',   24, 'f', 'IT'): 9999,
...     ('Japan',   23, 'f', 'IT'): 9000
... }
>>> {x: value for (w, x, y, z), value in data.items() if w == "America" and y == "m" and z == "IT"}
{25: 10000, 22: 8999}

您可以将整个try/except替换为以下内容:

res.setdefault((country, sex, job), {})[age] = cnt
或者您可以将res设置为defaultdict,然后它变成:

res[country, sex, job][age] = cnt

您可以将整个try/except替换为以下内容:

res.setdefault((country, sex, job), {})[age] = cnt
或者您可以将res设置为defaultdict,然后它变成:

res[country, sex, job][age] = cnt
由于我喜欢namedtuples,这里有一个替代建议:

将字典存储为一个列表或一组命名的元组,例如

要转换现有词典,请执行以下操作:

现在,您可以以非常可读的方式获取所需的条目,例如

>>> results = [i for i in nt if (i.country=='America' and i.sex=='m' and i.job=='IT')]
或者,例如,要获取计数:

编辑:性能 我不确定您是否在关注性能,因为您提到了更简单的方法。 你说得对,纯粹的理解速度更快:

dt = {
    ('America', 25, 'm', 'IT'): 10000,
    ('America', 22, 'm', 'IT'): 8999,
    ('Japan',   24, 'f', 'IT'): 9999,
    ('Japan',   23, 'f', 'IT'): 9000
}

nt = [Entry(*list(k) + [dt[k]]) for k in dt]

%timeit {i.age:i.count for i in nt if (i.country=='America' and i.sex=='m' and i.job=='IT')}

100000 loops, best of 3: 3.62 µs per loop

%timeit {x: value for (w, x, y, z), value in dt.items() if w == "America" and y == "m" and z == "IT"}

100000 loops, best of 3: 2.42 µs per loop
但是,如果你有一个更大的数据集,并且一遍又一遍地查询它,我也会考虑Pandas或SQLite

df = pd.DataFrame([list(x[0]) + [x[1]] for x in dt.items()])
df.columns = ['country', 'age', 'sex', 'job', 'count']
df
由于我喜欢namedtuples,这里有一个替代建议:

将字典存储为一个列表或一组命名的元组,例如

要转换现有词典,请执行以下操作:

现在,您可以以非常可读的方式获取所需的条目,例如

>>> results = [i for i in nt if (i.country=='America' and i.sex=='m' and i.job=='IT')]
或者,例如,要获取计数:

编辑:性能 我不确定您是否在关注性能,因为您提到了更简单的方法。 你说得对,纯粹的理解速度更快:

dt = {
    ('America', 25, 'm', 'IT'): 10000,
    ('America', 22, 'm', 'IT'): 8999,
    ('Japan',   24, 'f', 'IT'): 9999,
    ('Japan',   23, 'f', 'IT'): 9000
}

nt = [Entry(*list(k) + [dt[k]]) for k in dt]

%timeit {i.age:i.count for i in nt if (i.country=='America' and i.sex=='m' and i.job=='IT')}

100000 loops, best of 3: 3.62 µs per loop

%timeit {x: value for (w, x, y, z), value in dt.items() if w == "America" and y == "m" and z == "IT"}

100000 loops, best of 3: 2.42 µs per loop
但是,如果你有一个更大的数据集,并且一遍又一遍地查询它,我也会考虑Pandas或SQLite

df = pd.DataFrame([list(x[0]) + [x[1]] for x in dt.items()])
df.columns = ['country', 'age', 'sex', 'job', 'count']
df

你的问题是?@StefanPochmann是一个更简单的方法,你的问题是?@StefanPochmann是一个更简单的方法,但我认为namedtuples没有dict那么好,比如我想经常和国家、性别、工作打交道,你总是需要遍历列表,hash可能会执行得更好为什么Entry有参数*listk+[dt[k] ]?这里发生了什么。看起来Entry收到了一个键列表和一个值列表,但让我联想到的是两个列表之间的+号。但我认为namedtuple的性能不如dict好,比如我想经常访问国家、性别、工作,你总是需要遍历列表,哈希可能会更好。Entry有什么参数*listk+[dt[k]]?这里发生了什么。看起来Entry接收到了一个键列表和一个值列表,但抛出的是两个列表之间的+号。