Digamos que tengo una lista de tuplas con estados y condados:

stList = [('NJ', 'Burlington County'),
 ('NJ', 'Middlesex County'),
 ('VA', 'Frederick County'),
 ('MD', 'Montgomery County'),
 ('NC', 'Lee County'),
 ('NC', 'Alamance County')]

Para cada uno de estos elementos, quiero comprimir el estado con el condado, así:

new_list = [{'NJ': 'Burlington County'},
{'NJ': 'Middlesex County'},
{'VA': 'Frederick County'},
{'MD': 'Montgomery County'},
{'NC': 'Lee County'},
{'NC': 'Alamance County'}]

Intenté algo como esto, pero no funciona correctamente (itera a través de cada 'letra' y las comprime individualmente):

new_list = []
for item in stList:
  d1 = dict(zip(item[0], item[1]))
  new_list.append(d1)

Devuelve:

 [{'N': 'B', 'J': 'u'},
 {'N': 'M', 'J': 'i'},
 {'V': 'F', 'A': 'r'},
 {'M': 'M', 'D': 'o'},
 {'N': 'L', 'C': 'e'},
 {'N': 'A', 'C': 'l'}]

Para hacer las cosas más complicadas, mi objetivo final es tener una lista de diccionarios para cada estado (clave), que tenga los condados (valor) como una lista. ¿Cómo puedo arreglar el diccionario comprimido y luego poner los condados como una lista para cada estado?

final_list = [{'NJ': ['Burlington County', 'Middlesex County']},
{'VA': 'Frederick County'},
{'MD': 'Montgomery County'},
{'NC': ['Lee County', 'Alamance County'}]
1
gwydion93 14 sep. 2018 a las 17:42

5 respuestas

La mejor respuesta

Obtiene un resultado incorrecto porque zip trata las cadenas como iterables. Es comportamiento esperado.

Puede obtener algo parecido a lo que quiere de esta manera:

result = dict()
for state, county in stList:
    result.setdefault(state, list()).append(county)

print(result)

El resultado es un diccionario único con listas. Salida:

{'NJ': ['Burlington County', 'Middlesex County'], 'VA': ['Frederick County'], 'MD': ['Montgomery County'], 'NC': ['Lee County', 'Alamance County']}
7
Poolka 14 sep. 2018 a las 14:51

No creo que zip () sea adecuado para esto. Aquí hay dos posibles soluciones. Si tiene que usar una lista para almacenar los resultados, tendrá que ir un paso más allá después de esta respuesta. Sin embargo, si usar un dict para los resultados funcionaría, entonces esta respuesta podría llevarte allí:

 stList = [('NJ', 'Burlington County'),
 ('NJ', 'Middlesex County'),
 ('VA', 'Frederick County'),
 ('MD', 'Montgomery County'),
 ('NC', 'Lee County'),
 ('NC', 'Alamance County')]


new_list = []
for item in stList:
    new_list.append({item[0]:item[1]})

print "new list: ", new_list


new_dict = {}
for item in stList:
    if item[0] in new_dict:
        new_dict[item[0]].append(item[1])
    else:
        new_dict[item[0]] = [item[1]]

print "new dict: ", new_dict

Estas soluciones producen lo siguiente:

Nueva lista: [{'NJ': 'Condado de Burlington'}, {'NJ': 'Condado de Middlesex'}, {'VA': 'Condado de Frederick'}, {'MD': 'Condado de Montgomery'}, {' NC ':' Condado de Lee '}, {' NC ':' Condado de Alamance '}]

Nuevo dict: {'VA': ['Condado de Frederick'], 'NJ': ['Condado de Burlington', 'Condado de Middlesex'], 'NC': ['Condado de Lee', 'Condado de Alamance'], 'MD' : ['Condado de Montgomery']}

2
Phil S 14 sep. 2018 a las 15:11

La solución de setdefault de Poolka es sólida, eficiente y legible, pero puede hacerse aún más intuitiva con un defaultdict:

from collections import defaultdict

result = defaultdict(list)
for state, county in stList:
    result[state].append(county)

Si hay trillizos con fechas en su lista, puede hacer una versión anidada:

result = defaultdict(lambda: defaultdict(list))
for state, county, date in stList:
    result[state][county].append(date)

Para una línea sin ninguno de los atributos mencionados anteriormente, puede usar itertools.groupby;)

from itertools import groupby
{k: [x[1] for x in g] for k, g in groupby(sorted(stList), key=lambda x: x[0])}

# {'NC': ['Alamance County', 'Lee County'], 
#  'MD': ['Montgomery County'], 
#  'NJ': ['Burlington County', 'Middlesex County'], 
#  'VA': ['Frederick County']}

Algorítmicamente, esto es peor ya que tiene que ordenar el list inicial.

4
schwobaseggl 14 sep. 2018 a las 19:50

Lista de comprensión parece ser la forma más fácil aquí

[{i[0]:i[1]} for i in stList]

SALIDA

[{'NJ': 'Burlington County'},
{'NJ': 'Middlesex County'},
{'VA': 'Frederick County'},
{'MD': 'Montgomery County'},
{'NC': 'Lee County'},
{'NC': 'Alamance County'}]
2
Jonas Wolff 14 sep. 2018 a las 15:31

La razón por la que su código está roto probablemente se deba a un malentendido con zip. Básicamente trata cada nombre como un iterador separado e itera sobre los dos primeros caracteres s[:1]. Si desea una asignación entre estados y condados en cada estado, puede intentar esto:

mapping = {}
for state, cty in stList:
    if (state in mapping):
        mapping[state].append(cty)
    else:
        mapping[state] = [cty]

Esa es la forma más simple de hacerlo, en cualquier caso. Sin embargo, si desea usar itertools, puede hacer un groupby como este:

mapping = dict( [ (k, [gg[1] for gg in g]) for k, g in groupby(stList, key = lambda x: x[0]) ] )
1
Woody1193 14 sep. 2018 a las 15:01