2015-10-23 43 views
1

我有一些数据原本是这样的,我想在Python 2.7来处理其中:映射表具有复合主键的Python字典

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的所有不同值(如果这个想法不是很好,我宁愿把它保留为列表中,请让我知道了意见。)

我知道,一个Python字典需要一个哈希的关键,所以我可以通过连接idyear将一个字符串转换这个表,并且有类似

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

很明显,如果你想读出这个,这不是很优雅e密钥的单独部分。获得复合密钥字典的最容易的方法是什么,它仍然很容易成为json?

+1

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

回答

2

tuple是可哈希:

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

然而,这个字典不能dump版,在这种情况下,字典的关键应该是一个字符串:

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()} 

这双功能应该去,直到你开始使用足够复杂和/或其方法实施得不好的密钥。

+0

我还没有实现它,但这似乎是最好的主意。我还没有决定是否要使用'tuple'或'namedtuple'作为键。后者也是可散列的,对吧?你知道这是否已经触及了一个糟糕的'__repr__'和/或太复杂的密钥? – Roland

+1

@ namedtuple的@Roland'__repr__'足以满足'key == ast.literal_eval(repr(key))'的要求,而'json'字符串的发送者和接收者都具有与'namedtuple'相同的定义,在他们的范围内。这使得命名对象与元组没有太大区别,所以我会选择后者。元组占用RAM和'json'的空间较少,可能它们工作得更快。但是,如果你有很多这样的数据结构要发送到多个地方,应该选择'namedtuple',因为'explicit比隐式更好'。 – Vovanrock2002

2

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

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

你可以索引元组就像你索引列表,例如(1,2012)[1]2012

+0

如何将这样的字典转储到json中? – Roland

1

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

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

我的印象是'namedtuple's不容易转储'(参见http:// stackoverflow。com/questions/5906831/serializing-a-python-namedtuple-to-json) – Roland

+0

它需要一点点额外的努力,但是使用这种预定义的格式很容易。 – Wolph