如何将没有键的元组列表转换为dicts列表,重复使用单独的键列表?

时间:2016-01-29 19:47:27

标签: python list python-2.7 dictionary list-comprehension

我的问题

我的SQL查询结果包含仅包含值的元组列表,没有列名称。

我的数据子集可能如下所示:

dbSqlResults = [
    (u'Dave', u'Smith', u'dave@smith.bla with extra spaces   ', 1, 2, 3.2),
    (u'Valerie', u'Conklin', u'valconk@gmail.bla with extra spaces   ', 4, 5, 6.5),
    (u'Mighty Joe', u'Frazier', u'toughstuff@ko.bla with extra spaces   ', 7, 8, 9.8)
]

我想将其转换为dicts列表,并为每个dict条目重用相同的键列表,同时迭代行以添加值。键列表长度和每行元组中的值的数量是相同的维度;在我的实际数据中都包含11个条目。并且一些值在分配给字典之前需要修剪空格。

我想要应用于每个元组的键列表可能如下所示:

keys = ['first_name', 'last_name', 'email', 'partners', 'kids', 'meals_together']

如果合并得当,我希望最终看起来像:

listOfDicts = [
    {'first_name' : 'Dave', 'last_name' : 'Smith', 'email' : 'dave@smith.bla', 'partners' : 1, 'kids' : 2, 'meals_together' : 3.2},
    {'first_name' : 'Valerie', 'last_name' : 'Conklin', 'email' : 'valconk@gmail.bla', 'partners' : 4, 'kids' : 5, 'meals_together' : 6.5},
    {'first_name' : 'Mighty Joe', 'last_name' : 'Frazier', 'email' : 'toughstuff@ko.bla', 'partners' : 7, 'kids' : 8, 'meals_together' : 9.8}
]

研究

我查看了Create a dictionary with list comprehension in Python,但它没有帮助,因为它假定(k,v),而我列表中的每个元组都没有键和11个实际值。

我看了Different list values for dictionary keys但是输出错了,我想在结果中对每个元组重复应用一个键列表,因为我将它们转换为dicts列表。

我考虑过https://stackoverflow.com/a/5087977,但它似乎反复遍历行数组以获取每个列值,并且似乎不是列表理解的优雅应用。

我的解决方案

我想出的代码来解决这个问题:

# assuming rows looks like dbSqlResults as declared above...
def sqlResultsToLOD(rows):
    keys = ['first_name', 'last_name', 'email', 'partners', 'kids', 'meals_together']
    result = []
    for first_name, last_name, email, partners, kids, meals in rows:
        result.append({
            keys[0] : first_name.strip(),
            keys[1] : last_name.strip(),
            keys[2] : email.strip(),
            keys[3] : partners,
            keys[4] : kids,
            keys[5] : meals
        })
    return results

这给了我想要的输出,但感觉不是非常pythonic。感觉更像是在编写JavaScript。

我的问题

对此有什么更为pythonic和优雅的解决方案?

性能方面的一些细节是一个问题:

  • 我目前在每个元组中都有11个值
  • 我的结果集目前包含160万行元组,行数每天增长
  • 每个元组中的一些值在分配之前需要修剪空白(参见dbSqlResults数据,例如第3个字段)

如果我在研究中错过了答案,请提前感谢任何提示和道歉。

1 个答案:

答案 0 :(得分:3)

使用zip

>>> import pprint
>>> dbSqlResults = [
...     (u'Dave', u'Smith', u'dave@smith.bla with extra spaces   ', 1, 2, 3.2),
...     (u'Valerie', u'Conklin', u'valconk@gmail.bla with extra spaces   ', 4, 5, 6.5),
...     (u'Mighty Joe', u'Frazier', u'toughstuff@ko.bla with extra spaces   ', 7, 8, 9.8)
... ]
>>> keys = ['first_name', 'last_name', 'email', 'partners', 'kids', 'meals_together']
>>> pprint.pprint([dict(zip(keys, record)) for record in dbSqlResults])
[{'email': u'dave@smith.bla with extra spaces   ',
  'first_name': u'Dave',
  'kids': 2,
  'last_name': u'Smith',
  'meals_together': 3.2,
  'partners': 1},
 {'email': u'valconk@gmail.bla with extra spaces   ',
  'first_name': u'Valerie',
  'kids': 5,
  'last_name': u'Conklin',
  'meals_together': 6.5,
  'partners': 4},
 {'email': u'toughstuff@ko.bla with extra spaces   ',
  'first_name': u'Mighty Joe',
  'kids': 8,
  'last_name': u'Frazier',
  'meals_together': 9.8,
  'partners': 7}]

如果未将所有数据加载到内存中,也可以使用生成器功能。

def to_dict(records, keys):
    for record in records:
        for index, value in enumerate(record):
            if isinstance(value, (unicode, str)):
                record[index] = value.strip()
        yield dict(zip(keys, record))

然后:

for d in to_dict(dbSqlResults, keys):
    # do something