Объединение двух списков вложенных словарей по одинаковым значениям в Python - PullRequest
0 голосов
/ 08 сентября 2018

У меня есть два списка вложенных словарей:

lofd1 = [{'A': {'facebook':{'handle':'https://www.facebook.com/pages/New-Jersey/108325505857259','logo_id': None}, 'contact':{'emails':['nj@nj.gov','state@nj.gov']},'state': 'nj', 'population':'12345', 'capital':'Jersey','description':'garden state'}}]
lofd2 = [{'B':{'building_type':'ranch', 'city':'elizabeth', 'state':'nj', 'description':'the state close to NY'}}]

Мне нужно:

  • Объединить похожие словари в списках, используя значение ключа 'state' (например, объединить все словари, в которых "state" = "nj") в один словарь
  • Он должен включать комбинации ключ / значение, которые присутствуют в обоих словарях по одному разу (например, «state» для обоих должно быть «nj»)
  • Он должен включать комбинации ключ / значение, которых нет ни в одном из словарей (например, «население», «столица» из lofd1 и «building_type», «city» из lofd2).
  • Некоторые значения в словарях должны быть исключены, например, 'logo_id': нет
  • Поместите значения в "description" из обоих словарей в список строк, например, "" description ": ['штатное состояние', 'состояние, близкое к NY'] '

Окончательный набор данных должен выглядеть следующим образом:

lofd_final = [{'state': 'nj', 'facebook':{'handle':'https://www.facebook.com/pages/New-Jersey/108325505857259'},'population':'12345', 'capital':'Jersey', 'contact':{'emails':['nj@nj.gov','state@nj.gov']}, 'description': ['garden state','the state close to NY'],'building_type':'ranch', 'city':'elizabeth'}]

Каким было бы эффективное решение?

1 Ответ

0 голосов
/ 10 сентября 2018

Это решение очень специфично для вашего случая. С точки зрения сложности времени это; O(n*m), n - количество словарей в списке и m - количество ключей в словаре. Вы когда-либо просматривали каждый ключ в каждом словаре только один раз.

def extract_data(lofd, output):
    for d in lofd:
        for top_level_key in d: # This will be the A or B key from your example
            data = d[top_level_key] 
            state = data['state']
            if state not in output: # Create the state entry for the first time
                output[state] = {}
            # Now update the state entry with the data you care about
            for key in data:
                # Handle descriptions
                if key == 'description':
                    if 'description' not in output[state]:
                        output[state]['description'] = [data['description']]
                    else:
                        output[state]['description'].append(data['description'])
                # Handle all other keys
                else:
                    # Handle facebook key (exclude logo_id)
                    if key == 'facebook':
                        del data['facebook']['logo_id']
                    output[state][key] = data[key]

output = {}
extract_data(lofd1, output)
extract_data(lofd2, output)
print(list(output.values()))

output будет диктовкой с клавишами верхнего уровня в качестве состояний. Чтобы преобразовать его в указанное вами значение, просто извлеките значения в плоский список: list(output.values()) (см. Пример выше).

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

...