Я работаю над проблемой, где я хотел бы, чтобы плоский Python dict со списками в качестве значений, как показано ниже

[
    {'a': [1,2,3,4], 'b':[0,9,8], 'c': 'row1'},
    {'x': [1,2,3,4], 'y':[0,9,8], 'z': 'row2'}
]

К чему-то вроде

[
    {'a':1, 'b': 0, 'c': 'row1'},
    {'a':1, 'b': 9, 'c': 'row1'},
    {'a':1, 'b': 8, 'c': 'row1'},
    {'a':2, 'b': 0, 'c': 'row1'},
    {'a':2, 'b': 9, 'c': 'row1'},
    {'a':2, 'b': 8, 'c': 'row1'},
    {'a':3, 'b': 0, 'c': 'row1'},
    {'a':3, 'b': 9, 'c': 'row1'},
    {'a':3, 'b': 8, 'c': 'row1'},
    {'a':4, 'b': 0, 'c': 'row1'},
    {'a':4, 'b': 9, 'c': 'row1'},
    {'a':4, 'b': 8, 'c': 'row1'},
    {'x':1, 'y': 0, 'z': 'row2'},
    {'x':1, 'y': 9, 'z': 'row2'},
    {'x':1, 'y': 8, 'z': 'row2'},
    {'x':2, 'y': 0, 'z': 'row2'},
    {'x':2, 'y': 9, 'z': 'row2'},
    {'x':2, 'y': 8, 'z': 'row2'},
    {'x':3, 'y': 0, 'z': 'row2'},
    {'x':3, 'y': 9, 'z': 'row2'},
    {'x':3, 'y': 8, 'z': 'row2'},
    {'x':4, 'y': 0, 'z': 'row2'},
    {'x':4, 'y': 9, 'z': 'row2'},
    {'x':4, 'y': 8, 'z': 'row2'},
]

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

0
depyjs 16 Апр 2019 в 21:20

2 ответа

Лучший ответ

Вот рабочая реализация, которая сначала проверяет, какие записи словаря являются списком, вычисляет комбинации значений из этих списков, используя itertools.product, и генерирует словарь для каждой комбинации:

import itertools

input_list = [
    {'a': [1,2,3,4], 'b':[0,9,8], 'c': 'row1'},
    {'x': [1,2,3,4], 'y':[0,9,8], 'z': 'row2'}
]

output_list = []

for input_dict in input_list:
    list_keys = [] # store keys with list value
    for key,val in input_dict.items():
        if isinstance(val,list):
            list_keys.append(key)
    # eg. for the 1st dictionary in input_list:
    # list_keys = ['a','b']

    product = list(itertools.product(*[input_dict[list_key] for list_key in list_keys]))
    # eg. for the 1st dictionary in input_list:
    # product = [(1, 0), (1, 9), (1, 8), (2, 0), (2, 9), (2, 8), (3, 0), (3, 9), (3, 8), (4, 0), (4, 9), (4, 8)]

    # append a dictionary to the output list for each combination
    for combination in product:
        output_dict = input_dict.copy()
        for i,e in enumerate(combination):
            output_dict[list_keys[i]] = e
        output_list.append(output_dict)

print(output_list)

Выход:

[{'a': 1, 'b': 0, 'c': 'row1'},
{'a': 1, 'b': 9, 'c': 'row1'},
{'a': 1, 'b': 8, 'c': 'row1'},
{'a': 2, 'b': 0, 'c': 'row1'},
{'a': 2, 'b': 9, 'c': 'row1'},
{'a': 2, 'b': 8, 'c': 'row1'},
{'a': 3, 'b': 0, 'c': 'row1'},
{'a': 3, 'b': 9, 'c': 'row1'},
{'a': 3, 'b': 8, 'c': 'row1'},
{'a': 4, 'b': 0, 'c': 'row1'},
{'a': 4, 'b': 9, 'c': 'row1'},
{'a': 4, 'b': 8, 'c': 'row1'},
{'x': 1, 'y': 0, 'z': 'row2'},
{'x': 1, 'y': 9, 'z': 'row2'},
{'x': 1, 'y': 8, 'z': 'row2'},
{'x': 2, 'y': 0, 'z': 'row2'},
{'x': 2, 'y': 9, 'z': 'row2'},
{'x': 2, 'y': 8, 'z': 'row2'},
{'x': 3, 'y': 0, 'z': 'row2'},
{'x': 3, 'y': 9, 'z': 'row2'},
{'x': 3, 'y': 8, 'z': 'row2'},
{'x': 4, 'y': 0, 'z': 'row2'},
{'x': 4, 'y': 9, 'z': 'row2'},
{'x': 4, 'y': 8, 'z': 'row2'}]
0
glhr 16 Апр 2019 в 19:10

Вы можете использовать itertools.product для создания декартового произведения на элементы dict (учитывая ваш входной список в переменной l):

from itertools import product
[dict(p) for d in l for p in product(*([(k, i) for i in v] if isinstance(v, list) else [(k, v)] for k, v in d.items()))]

Это возвращает:

[{'a': 1, 'b': 0, 'c': 'row1'},
 {'a': 1, 'b': 9, 'c': 'row1'},
 {'a': 1, 'b': 8, 'c': 'row1'},
 {'a': 2, 'b': 0, 'c': 'row1'},
 {'a': 2, 'b': 9, 'c': 'row1'},
 {'a': 2, 'b': 8, 'c': 'row1'},
 {'a': 3, 'b': 0, 'c': 'row1'},
 {'a': 3, 'b': 9, 'c': 'row1'},
 {'a': 3, 'b': 8, 'c': 'row1'},
 {'a': 4, 'b': 0, 'c': 'row1'},
 {'a': 4, 'b': 9, 'c': 'row1'},
 {'a': 4, 'b': 8, 'c': 'row1'},
 {'x': 1, 'y': 0, 'z': 'row2'},
 {'x': 1, 'y': 9, 'z': 'row2'},
 {'x': 1, 'y': 8, 'z': 'row2'},
 {'x': 2, 'y': 0, 'z': 'row2'},
 {'x': 2, 'y': 9, 'z': 'row2'},
 {'x': 2, 'y': 8, 'z': 'row2'},
 {'x': 3, 'y': 0, 'z': 'row2'},
 {'x': 3, 'y': 9, 'z': 'row2'},
 {'x': 3, 'y': 8, 'z': 'row2'},
 {'x': 4, 'y': 0, 'z': 'row2'},
 {'x': 4, 'y': 9, 'z': 'row2'},
 {'x': 4, 'y': 8, 'z': 'row2'}]
0
blhsing 17 Апр 2019 в 13:20