Слияние словарей, если значения ключа объекта совпадают в python - PullRequest
2 голосов
/ 16 января 2020

Мне нужна помощь в объединении некоторых словарей на основе объекта в списке словарей. Возможно ли это?

Мои данные:

mongo_data = [{
 'url': 'https://goodreads.com/',
 'variables': [{'key': 'Harry Potter', 'value': '10.0'},
               {'key': 'Discovery of Witches', 'value': '8.5'},],
 'vendor': 'Fantasy' 
 },{
 'url': 'https://goodreads.com/',
 'variables': [{'key': 'Hunger Games', 'value': '10.0'},
               {'key': 'Maze Runner', 'value': '5.5'},],
 'vendor': 'Dystopia' 
 },{
 'url': 'https://kindle.com/',
 'variables': [{'key': 'Twilight', 'value': '5.9'},
               {'key': 'Lord of the Rings', 'value': '9.0'},],
 'vendor': 'Fantasy' 
 },{
 'url': 'https://kindle.com/',
 'variables': [{'key': 'The Handmaids Tale', 'value': '10.0'},
               {'key': 'Divergent', 'value': '9.0'},],
 'vendor': 'Fantasy' 
 }]

Мой код:

Я использовал [groupby] для группировки элементов с одинаковым URL.

from itertools import groupby, chain
import json

searches = []
for key, group in groupby(mongo_data, key=lambda chunk: chunk['url']):
    search = {}
    search["url"] = key
    search["results"] = [{"genre": result["vendor"], "data": result["variables"]} for result in group]
    searches.append(search)

print(json.dumps(searches))

Мой вывод

[
  {
    "url": "https://goodreads.com/",
    "results": [
      {
        "genre": "Fantasy",
        "data": [
          {
            "key": "Harry Potter",
            "value": "10.0"
          },
          {
            "key": "Discovery of Witches",
            "value": "8.5"
          }
        ]
      },
      {
        "genre": "Dystopia",
        "data": [
          {
            "key": "Hunger Games",
            "value": "10.0"
          },
          {
            "key": "Maze Runner",
            "value": "5.5"
          }
        ]
      }
    ]
  },
  {
    "url": "https://kindle.com/",
    "results": [
      {
        "genre": "Fantasy",
        "data": [
          {
            "key": "Twilight",
            "value": "5.9"
          },
          {
            "key": "Lord of the Rings",
            "value": "9.0"
          }
        ]
      },
      {
        "genre": "Fantasy",
        "data": [
          {
            "key": "The Handmaids Tale",
            "value": "10.0"
          },
          {
            "key": "Divergent",
            "value": "9.0"
          }
        ]
      }
    ]
  }
]

Как вы можете видеть под https://kindle.com/, у меня есть "genre":"Fantasy" дважды. Вместо этого печатаю дважды. Могу ли я объединить их без дубликатов.

Итак, я хочу, чтобы мой ожидаемый результат был:

{
    "url": "https://kindle.com/",
    "results": [
      {
        "genre": "Fantasy",
        "data": [
          {
            "key": "Twilight",
            "value": "5.9"
          },
          {
            "key": "Lord of the Rings",
            "value": "9.0"
          },
          {
            "key": "The Handmaids Tale",
            "value": "10.0"
          },
          {
            "key": "Divergent",
            "value": "9.0"
          }
        ]
      }
    ]
  }
]

Возможно ли это?

Ответы [ 3 ]

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

Вам нужен второй groupby , чтобы сгруппировать результат по поставщикам.

Например:

searches = []
for key, group in groupby(mongo_data, key=lambda chunk: chunk['url']):
    search = {"url": key, "results": []}
    for vendor, group2 in groupby(group, key=lambda chunk2: chunk2['vendor']):
        result = {
            "genre": vendor,
            "data": [{"key": key, "value": value}
                     for result2 in group2
                     for key, value in result2["variables"]],
        }
        search["results"].append(result)
    searches.append(search)

Список понимания используется для выравнивания result2["variables"] и избегайте списка списков.

Результат:

[
 {
  "url": "https://goodreads.com/",
  "results": [
   {
    "genre": "Fantasy",
    "data": [
     {
      "key": "key",
      "value": "value"
     },
     {
      "key": "key",
      "value": "value"
     }
    ]
   },
   {
    "genre": "Dystopia",
    "data": [
     {
      "key": "key",
      "value": "value"
     },
     {
      "key": "key",
      "value": "value"
     }
    ]
   }
  ]
 },
 {
  "url": "https://kindle.com/",
  "results": [
   {
    "genre": "Fantasy",
    "data": [
     {
      "key": "key",
      "value": "value"
     },
     {
      "key": "key",
      "value": "value"
     },
     {
      "key": "key",
      "value": "value"
     },
     {
      "key": "key",
      "value": "value"
     }
    ]
   }
  ]
 }
]
0 голосов
/ 16 января 2020

Если вы хотите "одну строку" (?), Попробуйте это:

{"url": "https://kindle.com/", "results": [{"genre": k,"data": [v]} for k, v in {g:[y for x in [x['variables'] for x in mongo_data if x['vendor'] == g] for y in x] for g in set(x['vendor'] for x in mongo_data)}.items()]}

Это дает

{
    'url': 'https://kindle.com/',
    'results': [
        {
            'genre': 'Fantasy',
            'data': [
                [
                    {'key': 'Harry Potter', 'value': '10.0'},
                    {'key': 'Discovery of Witches', 'value': '8.5'},
                    {'key': 'Twilight', 'value': '5.9'},
                    {'key': 'Lord of the Rings', 'value': '9.0'},
                    {'key': 'The Handmaids Tale', 'value': '10.0'},
                    {'key': 'Divergent', 'value': '9.0'}
                ]
            ]
        },

        {
            'genre': 'Dystopia',
            'data': [
                [
                    {'key': 'Hunger Games', 'value': '10.0'},
                    {'key': 'Maze Runner', 'value': '5.5'}
                ]
            ]
        }
    ]
}
0 голосов
/ 16 января 2020

Вы можете использовать этот код после for l oop для достижения sh того, что вы упомянули:

from collections import defaultdict

for item in searches:
    results = item['results']
    _res = defaultdict(list)
    for r in results:
        _res[r['genre']].append(r['data'])

    item['data'] = [{
        'genre': k,
        'data': _res[k]
    } for k in _res.keys()]

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