将dict的元组键转换为新的字典

时间:2015-06-05 06:13:46

标签: python dictionary tuples

我有dict这样:

{
    ('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']

我有更好的方法吗?因为这段代码看起来并不那么简单。

3 个答案:

答案 0 :(得分:5)

您可以使用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}

答案 1 :(得分:1)

因为我喜欢namedtuples,所以这里有另一种建议:

将您的字典存储为namedtuples的列表或集合,例如

>>> from collections import namedtuple
>>> Entry = namedtuple('entry', ('country', 'age', 'sex', 'job', 'count'))

转换现有字典dt

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

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

>>> results = [i for i in nt if (i.country=='America' and i.sex=='m' and i.job=='IT')]

或者,例如,获取count s:

>>> [i.count for i in nt if (i.country=='America' and i.sex=='m' and i.job=='IT')]
[8999, 10000]

编辑:效果

由于您提到了“更简单的方法”,因此不确定您是否在关注性能。 你是对的,纯粹的“理解力更快:

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

enter image description here

df.loc[(df.country=='America') & (df.sex=='m') & (df.job=='IT')]

enter image description here

答案 2 :(得分:0)

您可以替换整个尝试/除此之外:

Validator validator = Validation.byProvider( HibernateValidator.class )
        .configure()
        .failFast( true )
        .buildValidatorFactory()
        .getValidator();

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

defaultdict(dict)