Python defaultdict - 添加另一个键?

Python defaultdict - add another key?

我在这里可能没有使用正确的词,但基本上我想在提供的第一个键旁边添加另一个键。

这是我目前拥有的:

def transform_result(self, data):
    type_map = defaultdict(list)
    for entry in data:
        type_map[entry['type']].append({
            'id': entry['id'],
            'tag': entry['tag'],
        })
    ret = []
    for key, value, in type_map.items():
        ret.append({
            'type': key,
            'tags': value,
        })
    return ret

输入:

[
    OrderedDict([
        ('id', 1),
        ('type', 'Color'),
        ('writable', True),
        ('tag', 'Blue')
    ]),
    OrderedDict([
        ('id', 2),
        ('type', 'Color'),
        ('writable', True),
        ('tag', 'Red')
    ]),
    OrderedDict([
        ('id', 3),
        ('type', 'Color'),
        ('writable', True),
        ('tag', 'Green')
    ]),
    OrderedDict([
        ('id', 4),
        ('type', 'Shape'),
        ('writable', False),
        ('tag', 'Square')
    ]),
    OrderedDict([
        ('id', 5),
        ('type', 'Shape'),
        ('writable', False),
        ('tag', 'Circle')
    ])
]

期望的输出:

[
    {
        'type': 'Color',
        'writable': True,
        'tags': [
            {
                'tag': 'Blue',
                'id': 1
            },
            {
                'tag': 'Red',
                'id': 2
            },
            {
                'tag': 'Green',
                'id': 3
            }
        ]
    },
    {
        'type': 'Shape',
        'writable': False,
        'tags': [
            {
                'tag': 'Square',
                'id': 4
            },
            {
                'tag': 'Circle',
                'id': 5
            },

        ]
    },
]

这应该如何完成?


编辑:我明白了,抱歉我完全回避了这个。这是我的 hacky 解决方案:

def transform_result(self, data):
    type_map = defaultdict(list)
    for entry in data:
        type_map[entry['type'], entry['many']].append({
            'id': entry['id'],
            'tag': entry['tag'],
        })
    ret = []
    for key, value, in type_map.items():
        ret.append({
            'type': key[0],
            'many': key[1],
            'tags': value
        })
    return ret

基本上,让我感到困惑的是如何在第一个循环完成后访问 many。我的解决方案是快速将 typemany 放在一个小列表中,然后使用 [0][1] 访问它们,它有效!

这里给个建议,注意这个解是n*lg(n),你可以解n中的问题,但是如果你的数据集不是很大就无所谓了。用它作为灵感 ;)

from collections import OrderedDict
from itertools import groupby
from operator import itemgetter
from pprint import pprint


foo = [
    OrderedDict([
        ('id', 1),
        ('type', 'Color'),
        ('writable', True),
        ('tag', 'Blue')
    ]),
    ...
    ...
    ...
    OrderedDict([
        ('id', 5),
        ('type', 'Shape'),
        ('writable', False),
        ('tag', 'Circle')
    ])
]


def transform_result(data):
    key_func = itemgetter('type')
    for g, items in groupby(sorted(foo, key=key_func), key=key_func):
        item = {'type': g, 'tags': []}
        for i in items:
            item['writeable'] = i['writable']
            item['tags'].append({'tag': i['tag'], 'id': i['id']})
        yield item

pprint(list(transform_result(foo)))

输出

[{'tags': [{'id': 1, 'tag': 'Blue'},
           {'id': 2, 'tag': 'Red'},
           {'id': 3, 'tag': 'Green'}],
  'type': 'Color',
  'writeable': True},
 {'tags': [{'id': 4, 'tag': 'Square'}, {'id': 5, 'tag': 'Circle'}],
  'type': 'Shape',
  'writeable': False}]

我不能说我喜欢你的数据模型,但对于你给定的输入和期望的输出,你几乎拥有它:

def transform_result(self, data):
    type_map = defaultdict(list)
    for entry in data:
        type_map[entry['type'], entry['writable']].append({
            'id': entry['id'],
            'tag': entry['tag'],
        })
    ret = []
    for (k_type, k_writable), value in type_map.items():
        ret.append({
            'type': k_type,
            'writable': k_writable,
            'tags': value,
        })
    return ret