【问题标题】:Mapping a table with a compound primary key to a python dictionary将具有复合主键的表映射到 python 字典
【发布时间】:2016-01-22 18:23:43
【问题描述】:

我有一些最初看起来像这样的数据,我想在 Python 2.7 中处理:

id  year    value
1   2012    5
2   2012    50
3   2012    500
1   2013    6
2   2013    60
3   2013    600
1   2014    7
2   2014    70
3   2014    700

我可以很容易地将它转换成这样的列表[[1,2012,5],[2,2012,6],...]

我想将其转换为字典,因为我想查找固定 id 和/或 year 的所有不同值(如果这个想法不是很好,我宁愿保留它是一个列表,请在 cmets 中告诉我。)

我知道 python 字典需要一个可散列键,所以我可以通过将 idyear 连接到一个字符串来转换这个表,并有一个像

这样的字典
{'1_2012':'5','2_2012':'50', ...} 

显然,如果您想读出密钥的各个部分,这不是很优雅。将仍然很容易将dumpable 转换为 json 的复合键字典的最简单方法是什么?

【问题讨论】:

  • 如果你想以不同的方式查找,听起来你需要多个结构。请注意,字典键可以是元组,例如{(1, 2012): 5, ...} 有效;但是,我不知道 JSON 是否会处理它。

标签: python json python-2.7 dictionary composite-primary-key


【解决方案1】:

为此,我建议使用namedtuple,因为它比标准元组更清晰。

import collections
Key = collections.namedtuple('Key', ['id', 'year'])
data = {Key(id=1, year=2012): 5, Key(id=2, year=2012): 50}

【讨论】:

【解决方案2】:

tuple 是可散列的:

{(1, 2012): 5, (2, 2012): 50,}

但是,这个dict不能是dumped,这种情况下的dict键应该是字符串:

import json
import ast

# Works if keys satisfy following requirement:
# key == ast.literal_eval(repr(key))
# This is true for tuples having numbers inside.

def dumps(d):
    return json.dumps({repr(key): value for key, value in d.items()})

def loads(s):
    d = json.loads(s)
    return {ast.literal_eval(key): value for key, value in d.items()}

在您开始使用足够复杂的键和/或它们的 __repr__ 方法实施不佳之前,这对功能应该一直有效。

【讨论】:

  • 我还没有实现它,但这似乎是最好的主意。我还没有决定是否要使用tuplenamedtuple 作为键。后者也是可散列的,对吧?你知道这是否已经触及了__repr__ 和/或过于复杂的键区吗?
  • @Roland __repr__namedtuple 足以满足 key == ast.literal_eval(repr(key)) - 而 json 字符串的发送者和接收者在其范围内具有相同的 namedtuple 定义。这使得命名元组与元组没有太大区别,所以我会选择后者。元组在 RAM 和 json 中占用的空间更少,而且可能它们工作得更快。但是,如果您有很多这样的数据结构要在多个地方发送,则应该选择namedtuple,如explicit is better than implicit
【解决方案3】:

您可以使用元组作为键。您可以使用括号创建元组,例如(2,2012) 是一个元组。它们是不可变的,因此可以用作字典键:

d = {(1,2012):5, (2,2012):50}

您可以像索引列表一样索引元组,例如(1,2012)[1]2012

【讨论】:

  • 如何将这样的字典转储到 json 中?
猜你喜欢
  • 2018-11-28
  • 2016-08-31
  • 2020-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-28
  • 2017-06-28
  • 2017-08-06
相关资源
最近更新 更多