Tengo la siguiente lista:

my_list = [[['pd', 1],
           ['pd_de', None],
           ['pd_amnt', '$10.00']],
           [['pd', 1],
           ['pd_de', '5/1/19 '],
           ['pd_amnt', '$100.00 '],
           ['pd', 2],
           ['pd_de', '5/1/20 '],
           ['pd_amnt', '$200.00 ']],
           [['pd', 1],
           ['pd_de', None],
           ['pd_amnt', None]],
           [['pd', 1],
           ['pd_de', '5/1/19 '],
           ['pd_amnt', '$300.00 '],
           ['pd', 2],
           ['pd_de', '5/1/20 '],
           ['pd_amnt', '$600.00 '],
           ['pd', 3],
           ['pd_de', '6/1/18'],
           ['pd_amnt', '$450.00']]]

Con esto, me gustaría crear una lista de diccionarios. Estoy dong lo siguiente para crear una lista de diccionarios,

list_dict = []

for i in my_list:
    temp_dict = {}
    for j in i:
        temp_dict[j[0]] = j[1]
    list_dict.append(temp_dict)

Y estoy obteniendo una salida como esta, que no quiero,

[{'pd': 1, 'pd_de': None, 'pd_amnt': '$10.00'},
 {'pd': 2, 'pd_de': '5/1/20 ', 'pd_amnt': '$200.00 '},
 {'pd': 1, 'pd_de': None, 'pd_amnt': None},
 {'pd': 3, 'pd_de': '6/1/18', 'pd_amnt': '$450.00'}]

Necesito una salida como esta,

[{'pd_1': 1, 'pd_de_1': None, 'pd_amnt_1': '$10.00'},
 {'pd_1': 1, 'pd_de_1': '5/1/19', 'pd_amnt_1': '$100.00', 'pd_2': 2, 'pd_de_2': '5/1/20 ', 'pd_amnt_2': '$200.00 '},
 {'pd_1': 1, 'pd_de_1': None, 'pd_amnt_1': None},
 {'pd_1': 1, 'pd_de_1': '5/1/19', 'pd_amnt_1': '$300.00','pd_2': 2, 'pd_de_2': '5/1/20', 'pd_amnt': '$600.00','pd_3': 1, 'pd_de_3': '6/1/18', 'pd_amnt_3': '$450.00'}]

Si ve más arriba, están bien cuando la lista dentro tiene una longitud de 3. Si es más de 3, entonces no da el resultado correcto.

Tampoco estoy seguro de cómo crear "_" en las claves (es decir, 'pd_1') cuando creo claves para el diccionario.

¿Cómo puedo lograr el resultado deseado?

(Nota: no estoy seguro de cómo nombrar el título, dije longitud de la lista, podría estar equivocado allí porque no estoy familiarizado con los términos pitónicos)

0
user9431057 2 oct. 2019 a las 17:53

4 respuestas

La mejor respuesta
  • Encontré una forma realmente genial de hacer esto.
  • puede usar defaultdict para incrementar la clave cada vez que la vea. Y luego agréguelo a su diccionario result.
list_dict = []

from collections import defaultdict

for i in my_list:
    temp_dict = {}
    incr = defaultdict(int)
    for j in i:
        incr[j[0]] += 1
        temp_dict[j[0] + '_' + str(incr[j[0]])] = j[1]
    list_dict.append(temp_dict)

Salida:

[{'pd_1': 1, 'pd_de_1': None, 'pd_amnt_1': '$10.00'},
 {'pd_1': 1,
  'pd_de_1': '5/1/19 ',
  'pd_amnt_1': '$100.00 ',
  'pd_2': 2,
  'pd_de_2': '5/1/20 ',
  'pd_amnt_2': '$200.00 '},
 {'pd_1': 1, 'pd_de_1': None, 'pd_amnt_1': None},
 {'pd_1': 1,
  'pd_de_1': '5/1/19 ',
  'pd_amnt_1': '$300.00 ',
  'pd_2': 2,
  'pd_de_2': '5/1/20 ',
  'pd_amnt_2': '$600.00 ',
  'pd_3': 1,
  'pd_de_3': '6/1/18',
  'pd_amnt_3': '$450.00'}]
1
Poojan 2 oct. 2019 a las 15:12

Retener el orden de los artículos:

import pandas as pd
from collections import OrderedDict

# my_list = ...

res = []
for l1 in my_list:
    d = OrderedDict()
    for l2 in l1:
        if l2[0] == 'pd':
            sfx = l2[1]
        d[f'{l2[0]}_{sfx}'] = l2[1].strip() if isinstance(l2[1], str) else l2[1]
    res.append(d)

df = pd.DataFrame(res)
print(df)

La salida:

   pd_1 pd_de_1 pd_amnt_1  pd_2 pd_de_2 pd_amnt_2  pd_3 pd_de_3 pd_amnt_3
0     1    None    $10.00   NaN     NaN       NaN   NaN     NaN       NaN
1     1  5/1/19   $100.00   2.0  5/1/20   $200.00   NaN     NaN       NaN
2     1    None      None   NaN     NaN       NaN   NaN     NaN       NaN
3     1  5/1/19   $300.00   2.0  5/1/20   $600.00   3.0  6/1/18   $450.00
2
RomanPerekhrest 2 oct. 2019 a las 15:28

Puede usar una variable adicional (counter) para encontrar el "índice" clave que aún no existe en el diccionario:

result = []
for sub_list in my_list:
    temp = {}
    for key, value in sub_list:
        counter = 1
        while f"{key}_{counter}" in temp:
            counter  += 1
        temp[f"{key}_{counter}"] = value
    result.append(temp)

Una solución un poco más eficiente será almacenar los contadores en dict e incrementarlos una vez que se use la clave:

result = []
for sub_list in my_list:
    counters = {}
    temp = {}
    for key, value in sub_list:
        if key in counters:
            counters[key] += 1
        else:
            counters[key] = 1
        temp[f"{key}_{counters[key]}" ] = value
    result.append(temp)

Usando collections.defaultdict puede escribirlo un poco más corta:

from collections import defaultdict

result = []
for sub_list in my_list:
    counters = defaultdict(int)
    temp = {}
    for key, value in sub_list:
        counters[key] += 1
        temp[f"{key}_{counters[key]}"] = value
    result.append(temp)
1
Olvin Roght 2 oct. 2019 a las 15:46

La razón por la que obtiene esto es porque cuando establece una clave en un diccionario para algo, anulará cualquier dato anterior. Por ejemplo, tiene este diccionario x = ["a":1, "b":2, "c":3] si lo hace x["d"] = 4, será ["a":1, "b":2, "c":3, "d":4] pero si lo hace x["a"] = 3 será ["a":3, "b":2, "c":3, "d":4].
La solución para usted es agregar cada elemento al diccionario con un número después de la etiqueta para representar qué etiqueta es.

list_dict = []

for i in my_list:
    temp_dict = {}
    for j in i:
        a = 1
        while j[0]+"_"+str(a) in temp_dict:
            a += 1
        temp_dict[j[0]+"_"+str(a)] = j[1]
    list_dict.append(temp_dict)
-1
Hippolippo 2 oct. 2019 a las 15:03
58204041