【问题标题】:Merge lists of complex dicts with arbitrary keys合并具有任意键的复杂字典列表
【发布时间】:2020-01-08 16:16:32
【问题描述】:

我有这个代码:

dotteds = ["apple.orange.banana", "a.b.c", "a.b.d"]

name = "name"
avtype = "type"
fields = "fields"


main_dictionary_list = []

for x in dotteds:

    split_name = x.split('.')
    if len(split_name) > 1:
        value = {name: split_name[-1], avtype: 'string'}
        dicts = []
        for y in split_name:
            dicts.append({name: y, avtype: {name: y, avtype: "record", fields: []}})
        dicts[-1] = value

        value = value['name']+split_name[-1]

        for z in reversed(range(len(dicts))):
            if z != 0:
                dicts[z - 1]['type']['fields'].append(dicts[z])

        main_dictionary_list.append(dicts[0])

    else:
        dicts = []
        value = {name: split_name[-1], avtype: 'string'}
        dicts.append(value)
        main_dictionary_list.append(dicts[0])

print(main_dictionary_list)

这给了我这样的输出:

[{
        'name': 'apple',
        'type': {
            'name': 'apple',
            'type': 'record',
            'fields': [{
                    'name': 'orange',
                    'type': {
                        'name': 'orange',
                        'type': 'record',
                        'fields': [{
                                'name': 'banana',
                                'type': 'string'
                            }
                        ]
                    }
                }
            ]
        }
    }, {
        'name': 'a',
        'type': {
            'name': 'a',
            'type': 'record',
            'fields': [{
                    'name': 'b',
                    'type': {
                        'name': 'b',
                        'type': 'record',
                        'fields': [{
                                'name': 'c',
                                'type': 'string'
                            }
                        ]
                    }
                }
            ]
        }
    }, {
        'name': 'a',
        'type': {
            'name': 'a',
            'type': 'record',
            'fields': [{
                    'name': 'b',
                    'type': {
                        'name': 'b',
                        'type': 'record',
                        'fields': [{
                                'name': 'd',
                                'type': 'string'
                            }
                        ]
                    }
                }
            ]
        }
    }
]

理想情况下我需要:

[{
        'name': 'apple',
        'type': {
            'name': 'apple',
            'type': 'record',
            'fields': [{
                    'name': 'orange',
                    'type': {
                        'name': 'orange',
                        'type': 'record',
                        'fields': [{
                                'name': 'banana',
                                'type': 'string'
                            }
                        ]
                    }
                }
            ]
        }
    }, {
        'name': 'a',
        'type': {
            'name': 'a',
            'type': 'record',
            'fields': [{
                    'name': 'b',
                    'type': {
                        'name': 'b',
                        'type': 'record',
                        'fields': [{
                                'name': 'c',
                                'type': 'string'
                            }, 
                            {
                                'name': 'd',
                                'type': 'string'
                            }
                        ]
                    }
                }
            ]
        }
    }
]

我需要能够使用任意数量的组合来做到这一点:

apple.orange.banana、a.b.c、a.b.d、a.b.q.e.a.s.d 等

我不知道如何组合类似的“名称:键”组合。它旨在为 avro 格式。

我也尝试将虚线值放入字典中,这本身就有点麻烦。

【问题讨论】:

  • 你能退后一步,并为此提供更多背景/背景吗?
  • 看看avro4s-ui.landoop.com 我想这样做,但基于虚线名称,并插入我自己的类型值。 JSON ---> Avro 模式

标签: python list dictionary avro


【解决方案1】:

你可以使用递归collections.defaultdict:

from collections import defaultdict
def group(vals, last=None):
   if any(len(i) == 1 for i in vals):
      return [{'name':last, 'type':{'name':last, 'type':'record', 'fields':[{'name':i[0], 'type':'string'} if len(i) == 1 else group([i], i[0])[0] for i in vals]}}]
   _d = defaultdict(list)
   for i in vals:
      _d[i[0]].append(i[1:])
   return [{'name':a, 'type':group(b, last=a)} if last is None else 
              {'name':last, 'type':'record', 'fields':group(b, last=a)} for a, b in _d.items()]

import json
vals = ['apple.orange.banana', 'a.b.c', 'a.b.d']
print(json.dumps(group([i.split('.') for i in vals]), indent=4))

输出:

[
  {
    "name": "apple",
    "type": [
        {
            "name": "apple",
            "type": "record",
            "fields": [
                {
                    "name": "orange",
                    "type": {
                        "name": "orange",
                        "type": "record",
                        "fields": [
                            {
                                "name": "banana",
                                "type": "string"
                            }
                        ]
                    }
                }
            ]
        }
    ]
},
{
    "name": "a",
    "type": [
        {
            "name": "a",
            "type": "record",
            "fields": [
                {
                    "name": "b",
                    "type": {
                        "name": "b",
                        "type": "record",
                        "fields": [
                            {
                                "name": "c",
                                "type": "string"
                            },
                            {
                                "name": "d",
                                "type": "string"
                            }
                        ]
                    }
                }
            ]
        }
      ]
   }
]

vals = ['asd.2', 'asd.3', 'asd.5.3.4']
print(json.dumps(group([i.split('.') for i in vals]), indent=4))

输出:

[
  {
    "name": "asd",
    "type": [
        {
            "name": "asd",
            "type": {
                "name": "asd",
                "type": "record",
                "fields": [
                    {
                        "name": "2",
                        "type": "string"
                    },
                    {
                        "name": "3",
                        "type": "string"
                    },
                    {
                        "name": "5",
                        "type": "record",
                        "fields": [
                            {
                                "name": "5",
                                "type": "record",
                                "fields": [
                                    {
                                        "name": "3",
                                        "type": {
                                            "name": "3",
                                            "type": "record",
                                            "fields": [
                                                {
                                                    "name": "4",
                                                    "type": "string"
                                                }
                                            ]
                                        }
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
         }
      ]
   }
]

【讨论】:

  • 经过进一步检查,这很接近,但并不完美。试试这些值:asd.2、asd.3、asd.5.3.4
  • @tsai9_9 这些值的期望输出是什么?
  • 我希望它继续:"name": "asd", "type": { "name": asd", "type": "record", "fields" : [{"name ":"2", "type":"string"},{"name":"3", "type":"string"}, {"name":"5", "type":{"name" :“5”,“类型”:“记录”,“字段”:[“名称”:“3”,“类型”:{“名称”:“3”,“类型”:“记录”,“字段” : ["name": "4", "type": "string"]}]}]}}]. 你几乎是对的,因为当你没有不同的长度时它可以工作,(如果你做 asd. 2 和 asd.3 它会工作,如果你做 asd.5.3.4 和 asd.3 它会说索引超出范围),我只需要它在你把两个长度都放进去并且仍然结合它们时工作。
  • 你是最棒的!
  • @tsai9_9 很高兴为您提供帮助!
猜你喜欢
  • 2020-01-22
  • 2015-07-28
  • 2019-11-19
  • 2019-08-18
  • 2019-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多