У меня есть массив dict, например:
[{'id': 1, 'tags': ['tag_a', 'tag_b']}, {'id': 2, 'tags': ['tag_c', 'tag_b']}]
и я хотел бы преобразовать этот массив в новый массив на основе ticket_id
, и каждое значение tag
должно быть объектом в массиве.
Я почти сделал это, используя следующую функцию:
raw = [{'id': 1, 'tags': ['tag_a', 'tag_b']}, {'id': 2, 'tags': ['tag_c', 'tag_b']}]
def transform(ticket):
result = []
for tag in ticket.get('tags', []):
result.append({'ticket_id': ticket.get('id'), 'tag': tag, 'sync': '123'})
return result
print(list(map(transform, raw)))
Но он возвращает что-то вроде [[{...}], [{...}]]
и синтаксис выглядит странно.
Каков правильный подход, чтобы вернуть что-то вроде:
[{'ticket_id': 1, 'tag': 'tag_a', 'sync': '123'}, {'ticket_id': 1, 'tag': 'tag_b', 'sync': '123'}, ...]
Вам просто нужно сгладить результаты. По сути, вы использовали операцию карты, когда вам нужна была операция с плоской картой.
Вы можете сделать это за один раз, используя понимание вложенного списка:
[x for ticket in raw for x in transform(ticket)]
Конечно, вы могли бы сделать что-то вроде:
[x for xs in map(transform, raw) for x in xs]
Или просто обычный вложенный цикл будет работать.
Это один из способов сделать это с помощью вложенных циклов for. Более того, вам не нужно map
свою функцию. Вы можете просто передать список функции и распечатать. Проблема с вашим кодом заключалась в том, что вы использовали один цикл for, тогда как глубина (длина) вашего tags
была больше единицы.
raw = [{'id': 1, 'tags': ['tag_a', 'tag_b']}, {'id': 2, 'tags': ['tag_c', 'tag_b']}]
def transform(ticket):
result = []
for dic in raw:
for tag in dic['tags']:
result.append({'ticket_id': dic['id'], 'tag': tag, 'sync': '123'})
return result
print(transform(raw))
# [{'ticket_id': 1, 'tag': 'tag_a', 'sync': '123'}, {'ticket_id': 1, 'tag': 'tag_b', 'sync': '123'},
# {'ticket_id': 2, 'tag': 'tag_c', 'sync': '123'}, {'ticket_id': 2, 'tag': 'tag_b', 'sync': '123'}]