Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm Pythonic将dict列表转换为namedtuple列表的方法_Algorithm_List_Dictionary_Python - Fatal编程技术网

Algorithm Pythonic将dict列表转换为namedtuple列表的方法

Algorithm Pythonic将dict列表转换为namedtuple列表的方法,algorithm,list,dictionary,python,Algorithm,List,Dictionary,Python,我有一个目录的列表。需要将其转换为名元组的列表(首选)或简单的元组,同时用空格分割第一个变量 还有什么更像蟒蛇的方法吗? 我简化了我的代码。欢迎理解、gen表达式和itertools的使用 数据来源: dl = [{'a': '1 2 3', 'd': '*', 'n': 'first'}, {'a': '4 5', 'd': '*', 'n': 'second'}, {'a': '6', 'd': '

我有一个
目录的
列表
。需要将其转换为
名元组的
列表
(首选)或简单的
元组
,同时用空格分割第一个变量

还有什么更像蟒蛇的方法吗?

我简化了我的代码。欢迎理解、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用我的原始答案和您的初始解决方案指出了问题:

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

(我有点惭愧,我一开始没捡到这个,结果得了45分!)

改用@eryksun的建议:

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

我原来不正确的答案。除非您有一个
OrderedDict
列表,否则不要使用它


另一种选择,不确定它比其他选择好还是坏:

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的字段,您可以使用

some = namedtuple('some', set(k for k in d.keys() for d 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]

警告字典的
值()!如果这个解决方案有效,并且
a,d,n
确实是按这个顺序返回的,那么这只是巧合。如果您使用不同版本的Python或以不同的方式创建dict,它可能会崩溃。直接使用按键,就像@eryksun的评论一样。@PetrViktorin-哇,我不敢相信我错过了。谢谢你的更正@彼得维克托林我怎么能忘记。。。将使用
OrderedDict
instead找到
namedtuple('xxx',d.keys())(**d)
非常方便。
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]