Объединить два текста в отдельный список по идентификатору - PullRequest
0 голосов
/ 09 июня 2019

Я пытаюсь объединить объект на основе ключа specs, большая часть структуры ключей является согласованной, учитывая, что объединение произойдет только в том случае, если company_name совпадает (в этом примере у меня только одинcompany_name) и если только (имя, {цвет, тип, лицензия, описание) равны для нескольких списков.

[
{
    "company_name": "GreekNLC",
    "metadata": [
        {
            "name": "Bob",
            "details": [
                {
                    "color": "black",
                    "type": "bmw",
                    "license": "4DFLK",
                    "specs": [
                        {
                            "properties": [
                                {
                                    "info": [
                                        "sedan",
                                        "germany"
                                    ]
                                },
                                {
                                    "info": [
                                        "drive",
                                        "expensive"
                                    ]
                                }
                            ]
                        }
                    ],
                    "description": "amazing car"
                }
            ]
        },
        {
            "name": "Bob",
            "car_details": [
                {
                    "color": "black",
                    "type": "bmw",
                    "license": "4DFLK",
                    "specs": [
                        {
                            "properties": [
                                {
                                    "info": [
                                        "powerful",
                                        "convertable"
                                    ]
                                },
                                {
                                    "info": [
                                        "drive",
                                        "expensive"
                                    ]
                                }
                            ]
                        }
                    ],
                    "description": "amazing car"
                }
            ]
        }
    ]
}
]

Я ожидаю следующий вывод:

[
{
    "company_name": "GreekNLC",
    "metadata": [
        {
            "name": "Bob",
            "details": [
                {
                    "color": "black",
                    "type": "bmw",
                    "license": "4DFLK",
                    "specs": [
                        {
                            "properties": [
                                {
                                    "info": [
                                        "powerful",
                                        "convertable"
                                    ]
                                },
                                {
                                    "info": [
                                        "sedan",
                                        "germany"
                                    ]
                                },
                                {
                                    "info": [
                                        "drive",
                                        "expensive"
                                    ]
                                }
                            ]
                        }
                    ],
                    "description": "amazing car"
                }
            ]
        }
    ]
}
]

Код, который у меня есть,

headers = ['color', 'license', 'type', 'description']

def _key(d):
  return [d.get(i) for i in headers]

def get_specs(b):
  _specs = [c['properties'] for i in b for c in i['specs']]
  return [{"properties": [i for b in _specs for i in b]}]

def merge(d):
  new_merged_list = [[a, list(b)] for a, b in groupby(sorted(d, key=_key), key=_key)]
  k = [{**dict(zip(headers, a)), 'specs': get_specs(b)} for a, b in new_merged_list]
  return k

result = {'name': merge(c.get("details")) for i in data for c in i.get("metadata")}

print(json.dumps(result))

, но он не работает.Я получаю это

{"name": [{"color": "black", "specs": [{"properties": [{"info": 
["amazing", "strong"]}]}]}]}

1 Ответ

1 голос
/ 10 июня 2019

Операция, которую вы хотите выполнить, аналогична группировке: company_name, name, color, type, license и description.

. Вы можетеСоздайте кортеж всех автомобилей в виде пар ключ-значение и выполните заданную операцию с результирующим кортежем, сгруппируйте его по составному ключу и перестройте список.

from collections import defaultdict
from collections.abc import Hashable

def merge_spec_props(company_data):
    keyed_tuples = (
                ((
                co['company_name'],
                user['name'], 
                car_detail['color'], 
                car_detail['type'], 
                car_detail['license'],
                car_detail['description'],
                ), (
                    (k, v 
                    if isinstance(v, Hashable)
                    else tuple(v))
                    for k, v in prop.items()
                    )
                )
                for co in company_data
                for user in co['metadata']
                for car_detail in user['car_details']
                for spec in car_detail['specs']
                for prop in spec['properties'] 
                for k, v in prop.items()
                )
    uniq = set(keyed_tuples)
    grouped = defaultdict(list)
    for k, spec in uniq:
        grouped[k].append(spec)

    merged_lst = [
        {
            'company_name': company_name, 
            'metadata': [{
                'name': username,
                'car_details': [{
                        'color': car_color,
                        'type': car_type,
                        'license': car_license,
                        'specs': [dict(spec)
                            for spec in specs
                        ],
                        'description': desc
                }]
            }]
        }
        for (company_name, username, car_color, car_type, car_license, desc), specs in grouped.items()
    ]

    return merged_lst

Хотя эта реализация очень специфична для ваших данных ивозможно, эта функция не может использоваться как повторно используемое значение для данных другого типа.Если бы description отличались в любом из car_details, в другой компании были бы введены только самые последние.

Следует отметить, что это не объединяет промежуточные поля.Возможный способ - это преобразовать данные в дерево и выполнить трансверсал по порядку, чтобы получить объединенную структуру.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...