繁体   English   中英

Pythonic将dicts列表转换为namedtuples列表的方法

[英]Pythonic way to convert list of dicts into list of namedtuples

我有一份dict list 需要将其转换为namedtuple (首选)或简单tuple list ,同时按空格分割第一个变量。

什么是pythonic方式呢?

我稍微简化了我的代码。 欢迎使用理解,gen表达式和itertools。

数据在:

dl = [{'a': '1 2 3',
       'd': '*',
       'n': 'first'},
      {'a': '4 5',
       'd': '*', 'n':
       'second'},
      {'a': '6',
       'd': '*',
       'n': 'third'},
      {'a': '7 8 9 10',
       'd': '*',
       'n': 'forth'}]

简单的算法:

from collections import namedtuple

some = namedtuple('some', ['a', 'd', 'n'])

items = []
for m in dl:
    a, d, n = m.values()
    a = a.split()
    items.append(some(a, d, n))

输出:

[some(a=['1', '2', '3'], d='*', n='first'),
 some(a=['4', '5'], d='*', n='second'),
 some(a=['6'], d='*', n='third'),
 some(a=['7', '8', '9', '10'], d='*', n='forth')]

下面,@ Petr Viktorin指出我的原始答案和您的初始解决方案的问题:

警告! 字典的values()没有任何特定的顺序! 如果这个解决方案有效,并且a,d,n确实按顺序返回,那只是巧合。 如果您使用不同版本的Python或以不同的方式创建dicts,它可能会破坏。

(我有点羞愧,我一开始没有接受这个,并获得了45个代表!)

请改用@ eryksun的建议:

items =  [some(m['a'].split(), m['d'], m['n']) for m in dl]

我原来的错误答案。 除非您有OrderedDict列表,否则不要使用它。

items =  [some(a.split(), d, n) for a,d,n in (m.values() for m in dl)]

以为我会因为我非常喜欢这个名字和字典而在这里发声!

这里有一个列表理解,其中包含dict理解,可以对字典进行初始处理:

split_dictionaries = \ 
    [{key: value.split() for k, value in d.iteritems()} for d in dl] 

我经常使用我称之为“特百惠”的食谱,递归地将字典转换为命名元组。 有关代码,请参阅此处的要点 这是一个简化的部分,在这里集成,并有一个非常干净的方式来执行此操作。

import collections

def namedtuple_from_mapping(mapping, name="Tupperware"):
    this_namedtuple_maker = collections.namedtuple(name, mapping.iterkeys())
    return this_namedtuple_maker(**mapping)

所以给定这个函数,你可以这样做 - 我们很快就会重构:

split_namedtuples = [ 
    namedtuple_from_mapping(
        {key: value.split() for k, value in d.iteritems()}
    ) for d in dl
]   

现在具有更好的封装和可读性:

def format_string(string):
    return string.split()

def format_dict(d):
    return {key: format_string(value) for key, value in d.iteritems()}

formatted_namedtuples = [namedtuple_from_mapping(format_dict(d)) for d in dl]

另一种选择,不确定它是否比其他更好或更差:

class some(namedtuple('some', 'a d n')):
    def __new__(cls, **args):
        args['a'] = args['a'].split()
        return super(some, cls).__new__(cls, **args)

items = list(some(**m) for m in dl)

顺便说一句,我不是绝对致力于为基类相同的名称作为子类some 我喜欢它,因为它意味着生成的类使用名称some转换为字符串,并且它从来没有特别引起我的问​​题,但如果你使用类名调试它可能会令人困惑。 所以要小心。

或者使用不同技巧的相同想法:

some = namedtuple('some', 'a d n')

def make_some(args):
    args = args.copy()
    args['a'] = args['a'].split()
    return some(**args)

items = map(make_some, dl) # NB: this doesn't return a list in Python 3

另外,@ detly提供的答案,如果您事先不知道dicts的字段,可以构造一个namedtuple类,

some = namedtuple('some', set(k for k in d.keys() for d in dl))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM