Слияние списков сложных диктов с произвольными ключами - PullRequest
0 голосов
/ 08 января 2020

У меня есть этот код:

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, ab c, abd, abqeasd и др. c.

I не могу понять, как комбинировать подобные комбинации «имя: ключ». Он предназначен для формата avro.

Я также пытался преобразовать пунктирные значения в словарь, что само по себе немного проблематично.

1 Ответ

1 голос
/ 08 января 2020

Вы можете использовать рекурсию с 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"
                                                }
                                            ]
                                        }
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
         }
      ]
   }
]
...