[pyar] Dict de listas de listas a csv

Ignacio Rossi rossi.ignacio en gmail.com
Lun Oct 5 20:49:45 ART 2015


Buenas

>Más vale, vos querés "explotar" el diccionario en varios diccionarios
>que representan las filas implícitas.
>Con una combinación de flatten y zip_longest deberías poder lograrlo:

Creo que lo que está buscando no es el flatten a secas, pero se le parece
mucho.
Fijate que en uno de los ejemplos que cuenta pasa de

> el dict:
> a: 1,
> b: [2,1]
> c: [[3,4],[5]]

a:

> a,b,c
> 1,2,3
> '','',4
> '',1,5

Si fuera flatten asi nomás el 1 de la columna b debería estár en la segunda
fila y no en la tercera.

Lo siguiente es lo mejor que se me ocurrió que se parece a lo que Franco
está buscando, capaz él pueda confirmar si voy por buen camino o estoy
mandando fruta.

a) Lo que sigue tiene sentido solo si los valores del diccionario original
son *hasta* listas de listas. i.e. entendí que no puede haber 3 listas
anidadas.
b) Los valores "se agrupan" segun el indice en cada una de las listas más
exteriores. En el ejemplo de arriba, el indice 0 sería (a=[1], b=[2],
c=[3,4], ) y el indice 1 (a=[], b=[1], c=[5], )
c) sobre esos grupos se hace el zip_longuest, como hace Claudio después del
flatten.

Es la mejor manera que encontré de explicar las diferencias de alineacion
entre lo que postea Franco y la solución de Claudio.
Acá va el código de Claudio con estos cambios.

Antes, un detalle ultra menor, pero nunca está de más repetirlo:
izip_longest devuelve None para los valores que no existen. Si uno hace

x or ''

para cambiar los None por el string vacío, no hay que olvidarse que eso
tambien convierte los ceros (o cualquier cosa que sea ~False para python).
Capaz no hay ceros en el input y esto no cambia nada. Yo puse una
funcioncita aparte para chequear eso :)


>>> import itertools, csv, sys
>>>
>>> def list_wrap(x):
...     return x if isinstance(x, list) else [x]
...
>>> def check_none(x):
...     return '' if x is None else x
...
>>> d = {'a':1,'b':[2, 1], 'c':[[3,4],5]}
>>>
>>> d = {k: list_wrap(y) for k, y in d.items()}
>>>
>>> D = []
>>> for lists in itertools.izip_longest(d['a'], d['b'], d['c']):
...     lists = [list_wrap(l) for l in lists]
...     for a, b, c in itertools.izip_longest(*lists):
...         aux = dict(a=a, b=b, c=c)
...         D.append({k: check_none(v) for k, v in aux.items()})
...
>>> w = csv.DictWriter(sys.stdout, ['a','b','c'])
>>> w.writeheader()
a,b,c
>>> w.writerows(D)
1,2,3
,,4
,1,5


Saludos

Ignacio








El 5 de octubre de 2015, 17:08, Claudio Freire <klaussfreire en gmail.com>
escribió:

> Más vale, vos querés "explotar" el diccionario en varios diccionarios
> que representan las filas implícitas.
>
> Con una combinación de flatten y zip_longest deberías poder lograrlo:
>
> >>> def flatten(x):
> ...    rv = []
> ...    if isinstance(x, list):
> ...        for i in x:
> ...           rv.extend(flatten(i))
> ...    else:
> ...        rv.append(x)
> ...    return rv
> >>> import sys,csv,itertools
> >>> w = csv.DictWriter(sys.stdout, ['a','b','c'])
> >>> d = {'a':2,'b':[[3,4],5], 'c':[6,7,8]}
> >>> D = [ dict(a=a or '', b=b or '', c=c or '') for a,b,c in
> itertools.izip_longest(*map(flatten, [d['a'],d['b'],d['c']])) ]
> >>> D
> [{'a': 2, 'c': 6, 'b': 3}, {'a': '', 'c': 7, 'b': 4}, {'a': '', 'c':
> 8, 'b': 5}]
> >>> w.writeheader()
> a,b,c
> >>> w.writerows(D)
> 2,3,6
> ,4,7
> ,5,8
>
>
>
> 2015-10-05 16:40 GMT-03:00 Franco Rodríguez <franco.rodriguezf en gmail.com>:
> > Hola chicos, cómo andan?
> >
> > Escribo por acá porque ya no sé cómo hacer con algo.
> >
> > Tengo que escribir un CSV con los valores que vienen en un dict, pero los
> > values del dict pueden ser listas (inclusive listas de listas), y estos
> se
> > deben escribir un valor por fila del csv. No encuentro la forma. Les paso
> > varios ejemplos:
> >
> > el dict:
> > a: 1,
> > b: [2,1]
> > c: [[3,4],[5]]
> >
> > debe escribirse como:
> >
> > a,b,c
> > 1,2,3
> > '','',4
> > '',1,5
> >
> > el dict:
> > a: 2,
> > b: [[3,4], 5]
> > c: [6,7,8]
> >
> > como:
> >
> > a,b,c
> > 2,3,6
> > '',4,''
> > '',5,7
> > '','',8
> >
> > el dict:
> > a: [1]
> > b: [[2],[3]],4]
> > c: [[5],[6]]
> >
> > a,b,c
> > 1,2,5
> > '',3,6
> > '',4,''
> >
> > La primer fila siempre va completa (con los primeros elementos de cada
> > value), y nunca hay una fila con todos vacíos.
> >
> > Lo encaré usando pandas (sé muy poco), usando recursividad, usando
> índices,
> > y la verdad es que me cansé.
> > Por ahí alguien me puede iluminar aunque sea un poco, muchas gracias.
> >
> > (de momento me alcanzaría con algún método que me equipare, por ejemplo:
> > el dict:
> > a: 2,
> > b: [[3,4], 5]
> > c: [6,7,8],
> > me lo convierta en:
> > el dict:
> > a: [[2,''],'', ''],
> > b: [[3,4], 5, '']
> > c: [[6,''],7,8]
> > )
> >
> > _______________________________________________
> > pyar mailing list pyar en python.org.ar
> > http://listas.python.org.ar/listinfo/pyar
> >
> > PyAr - Python Argentina - Sitio web: http://www.python.org.ar/
> >
> > La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
> > Argentina - http://www.usla.org.ar
> _______________________________________________
> pyar mailing list pyar en python.org.ar
> http://listas.python.org.ar/listinfo/pyar
>
> PyAr - Python Argentina - Sitio web: http://www.python.org.ar/
>
> La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
> Argentina - http://www.usla.org.ar
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.python.org.ar/pipermail/pyar/attachments/20151005/62aa8f02/attachment-0001.html>


More information about the pyar mailing list