将带有元组列表的字典转换为列表

时间:2016-05-20 00:24:50

标签: python list python-3.x dictionary tuples

假设我有一个具有这种结构的字典:

namedict = {
1880: 
    [('Mary', 'F', '7065', 1), 
     ('Anna', 'F', '2604', 2), 
     ('John', 'M', '9655', 1)],
1881: 
    [('Mary', 'F', '8065', 1), 
     ('Anna', 'F', '9604', 2), 
     ('John', 'M', '5655', 1)],
1882: 
    [('Mary', 'F', '9065', 1), 
     ('Anna', 'F', '9604', 2), 
     ('John', 'M', '5655', 1)]
    }

我想转换字典,以便数据采用以下列表结构:

[{(Mary, F): {1880: [7065, 1], 1881: [8065, 1], 1882: [9065, 1]}]
[{(Anna, F): {1880: [2064, 2], 1881: [9604, 2], 1882: [9604, 1]}]...

有关我将如何做的任何建议?

2 个答案:

答案 0 :(得分:1)

据我所知,collections.defaultdict()在这种情况下可以提供帮助:

from collections import defaultdict
from pprint import pprint

namedict = {
    1880:
        [('Mary', 'F', '7065', 1),
         ('Anna', 'F', '2604', 2),
         ('John', 'M', '9655', 1)],
    1881:
        [('Mary', 'F', '8065', 1),
         ('Anna', 'F', '9604', 2),
         ('John', 'M', '5655', 1)],
    1882:
        [('Mary', 'F', '9065', 1),
         ('Anna', 'F', '9604', 2),
         ('John', 'M', '5655', 1)]
}

d = defaultdict(dict)
for key, values in namedict.items():
    for name, gender, value1, value2 in values:
        d[(name, gender)][key] = [value1, value2]

pprint(dict(d))

打印:

{('Anna', 'F'): {1880: ['2604', 2], 1881: ['9604', 2], 1882: ['9604', 2]},
 ('John', 'M'): {1880: ['9655', 1], 1881: ['5655', 1], 1882: ['5655', 1]},
 ('Mary', 'F'): {1880: ['7065', 1], 1881: ['8065', 1], 1882: ['9065', 1]}}

或者,在Python3的情况下,您可以使用extended iterable unpacking并使解决方案更通用:

d = defaultdict(dict)
for key, values in namedict.items():
    for name, gender, *values in values:
        d[(name, gender)][key] = values

答案 1 :(得分:0)

根据我对问题的理解,以下代码应该有效。它使用了defaultdict(我最近开始使用的更多,但值得注意的是,another answer也使用它)

from collections import defaultdict
def reorder_namedict(namedict):
    new_list_representation = defaultdict(dict)
    for year in namedict:
        for user_tuple in namedict[year]:
            # tuple unpacking has changed based on what version of python is used.
            # I ran this against 3.4.3 and 2.7.6.
            # Use python --version to check if you don't know your version
            name, gender, num1, num2 = user_tuple
            new_list_representation[str((name, gender,))][year] = [int(num1), int(num2)]

    new_list = []

    # sorted so that it comes out in consistent order for string matching
    for key in sorted(new_list_representation):
        new_list.append([{key: new_list_representation[key]}])

    return new_list

代码返回列表列表以匹配问题中的第二个代码块。以下输入来自问题(加上或减去一些格式)和预期输出(来自问题,通过小修改返回所需列表的列表,而不是尝试返回多个列表。

namedict = {
1880: 
[('Mary', 'F', '7065', 1), 
('Anna', 'F', '2604', 2), 
('John', 'M', '9655', 1)],
1881: 
[('Mary', 'F', '8065', 1), 
('Anna', 'F', '9604', 2), 
('John', 'M', '5655', 1)],
1882: 
[('Mary', 'F', '9065', 1), 
('Anna', 'F', '9604', 2), 
('John', 'M', '5655', 1)]
}

output_to_match = [
[{str(('Anna', 'F',)): {1880: [2604, 2], 1881: [9604, 2], 1882: [9604, 2],}}],
[{str(('John', 'M',)): {1880: [9655, 1], 1881: [5655, 1], 1882: [5655, 1],}}],
[{str(('Mary', 'F',)): {1880: [7065, 1], 1881: [8065, 1], 1882: [9065, 1],}}],
]

以下代码将演示两个列表是否相同。您可以取消注释显示每个列表以及如何将其转换为字符串的打印语句,但我发现让代码检查每个字符匹配是否更可靠(我自己错过了一些小错误)。

match_this = str(output_to_match)
iTried = str(reorder_namedict(namedict))
# print(match_this)
# print('---')
# print(iTried)
for i in range(0, len(match_this)):
    if not match_this[i] == iTried[i]:
        print('%d %s %s' % (i, match_this[i], iTried[i],))
print(match_this == iTried)