基于匹配的dict键创建(k,v1,...,vn)元组

时间:2011-11-01 14:32:39

标签: python

我正在使用Python 2.6,我有两个数据集,每个数据集都是一个字典列表。这两个数据集如下所示:

[{'foo': 3}, {'bar': 4}]
[{'bar': 1}, {'foo': 8}]

从这两个数据集中,我想为输入数据创建一个单独的元组列表:

[('foo', 3, 8), ('bar', 4, 1)]

重要的是,第一个数据集中的数字首先出现在生成的元组中,顺便说一下。

我实际上通过各种方式(包括嵌套列表理解)实现了这一点,但似乎它应该更简单/更清晰。我很惊讶在itertools中没有任何东西跳出来(虽然我确实做了一个带链的实现,导致了一个2元组,其中int是在列表中)。任何人都可以提供干净的解决方案,还是只有一个?

2 个答案:

答案 0 :(得分:3)

您可以使用defaultdict

from collections import defaultdict

datasets = [{'foo': 3}, {'bar': 4}], [{'bar': 1}, {'foo': 8}]    

result = defaultdict(list)

for dataset in datasets:
    for eachdict in dataset:
        for key, value in eachdict.iteritems():
            result[key].append(value)

# the nested loops as a one-liner (utterly unnecessary):
# any(result[key].append(value) for dataset in datasets 
#                               for eachdict in dataset 
#                               for key, value in eachdict.iteritems())


# if you really need your output in exactly that format:
# result = [(key,) + tuple(values) for key, values in result.iteritems()]
print result

这对我来说似乎是最干净的方法。

答案 1 :(得分:2)

这是一个inner join operation,我们有一个工具可以做到这一点:

>>> ds1 = [{'foo': 3}, {'bar': 4}]
>>> ds2 = [{'bar': 1}, {'foo': 8}]

>>> import sqlite3
>>> c = sqlite3.connect(':memory:')
>>> c.execute('CREATE TABLE ds1 (key text PRIMARY KEY, value text)')
>>> c.execute('CREATE TABLE ds2 (key text PRIMARY KEY, value text)')
>>> c.executemany('INSERT INTO ds1 VALUES (?, ?)', [d.items()[0] for d in ds1])
>>> c.executemany('INSERT INTO ds2 VALUES (?, ?)', [d.items()[0] for d in ds2])
>>> c.commit()
>>> r = c.execute('SELECT ds1.key, ds1.value, ds2.value FROM ds1 INNER JOIN ds2 ON ds1.key=ds2.key')
>>> list(r)
[(u'foo', u'3', u'8'), (u'bar', u'4', u'1')]

sqlite3 module附带Python,不需要您创建和维护实际数据库,以便对数据集执行SQL查询。因此,如果您没有从数据库获取数据并且无法更改查询以便以最适合您的应用程序的形式将其恢复,您仍然可以使用SQL按摩数据,这非常方便。

使用SQL方法有几个优点1)代码清楚地表达了它的意图(我在公共密钥上加入两个数据集),2)它使得更容易考虑正确性问题(例如一个数据集中存在的密钥,但不是另一方面,3)很容易扩展到多个字段或切换到多字段键,4)可以指定排序。