valor resueltos recorrer que lista elementos ejercicios ejemplo diccionarios diccionario convertir buscar agregar python python-2.7 pretty-print ordereddictionary pprint

python - resueltos - ¿Hay alguna manera de imprimir correctamente los diccionarios ordenados?



que es un diccionario en python (11)

Aquí hay otra respuesta que funciona anulando y utilizando internamente la función stock pprint() . A diferencia de mi anterior , manejará OrderedDict dentro de otro contenedor, como una list y también podrá manejar cualquier argumento de palabra clave opcional, sin embargo, no tiene el mismo grado de control sobre el resultado que el otro.

Funciona redireccionando la salida de la función stock en un búfer temporal y luego ajusta la palabra antes de enviarla a la secuencia de salida. Si bien el resultado final producido no es excepcionalmente bonito, es decente y puede ser "lo suficientemente bueno" como para utilizarlo como solución alternativa.

Actualización 2.0

Simplificado mediante el uso del módulo de textwrap biblioteca estándar, y modificado para funcionar en Python 2 y 3.

from collections import OrderedDict try: from cStringIO import StringIO except ImportError: # Python 3 from io import StringIO from pprint import pprint as pp_pprint import sys import textwrap def pprint(object, **kwrds): try: width = kwrds[''width''] except KeyError: # unlimited, use stock function pp_pprint(object, **kwrds) return buffer = StringIO() stream = kwrds.get(''stream'', sys.stdout) kwrds.update({''stream'': buffer}) pp_pprint(object, **kwrds) words = buffer.getvalue().split() buffer.close() # word wrap output onto multiple lines <= width characters try: print >> stream, textwrap.fill('' ''.join(words), width=width) except TypeError: # Python 3 print(textwrap.fill('' ''.join(words), width=width), file=stream) d = dict(((''john'',1), (''paul'',2), (''mary'',3))) od = OrderedDict(((''john'',1), (''paul'',2), (''mary'',3))) lod = [OrderedDict(((''john'',1), (''paul'',2), (''mary'',3))), OrderedDict(((''moe'',1), (''curly'',2), (''larry'',3))), OrderedDict(((''weapons'',1), (''mass'',2), (''destruction'',3)))]

Muestra de salida:

pprint(d, width=40)

» {''john'': 1, ''mary'': 3, ''paul'': 2}

pprint(od, width=40)

» OrderedDict([(''john'', 1), (''paul'', 2),
(''mary'', 3)])

pprint(lod, width=40)

» [OrderedDict([(''john'', 1), (''paul'', 2),
(''mary'', 3)]), OrderedDict([(''moe'', 1),
(''curly'', 2), (''larry'', 3)]),
OrderedDict([(''weapons'', 1), (''mass'',
2), (''destruction'', 3)])]

Me gusta el módulo de pprint en Python. Lo uso mucho para probar y depurar. Frecuentemente utilizo la opción de ancho para asegurarme de que la salida encaja bien dentro de la ventana de mi terminal.

Funcionó bien hasta que agregaron el nuevo tipo de diccionario ordenado en Python 2.7 (otra característica genial que realmente me gusta). Si trato de imprimir bastante un diccionario ordenado, no se muestra bien. En lugar de tener cada pareja clave-valor en su propia línea, todo se muestra en una línea larga, que se envuelve muchas veces y es difícil de leer.

¿Alguien aquí tiene una forma de hacer que se imprima bien, como los viejos diccionarios sin orden? Probablemente podría resolver algo, posiblemente usando el método PrettyPrinter.format, si paso el tiempo suficiente, pero me pregunto si alguien aquí ya conoce una solución.

ACTUALIZACIÓN: Archivé un informe de error para esto. Puedes verlo en http://bugs.python.org/issue10592 .


Aquí hay una forma de pprint la implementación de pprint . pprint ordena las claves antes de imprimir, por lo que para pprint el orden, solo tenemos que hacer que las claves se clasifiquen de la manera que deseamos.

Tenga en cuenta que esto afecta la función items() . Por lo tanto, es posible que desee conservar y restaurar las funciones anuladas después de hacer la impresión.

from collections import OrderedDict import pprint class ItemKey(object): def __init__(self, name, position): self.name = name self.position = position def __cmp__(self, b): assert isinstance(b, ItemKey) return cmp(self.position, b.position) def __repr__(self): return repr(self.name) OrderedDict.items = lambda self: [ (ItemKey(name, i), value) for i, (name, value) in enumerate(self.iteritems())] OrderedDict.__repr__ = dict.__repr__ a = OrderedDict() a[4] = ''4'' a[1] = ''1'' a[2] = ''2'' print pprint.pformat(a) # {4: ''4'', 1: ''1'', 2: ''2''}


Como una solución temporal, puede intentar descargar en formato JSON. Pierdes algún tipo de información, pero se ve bien y mantiene el orden.

import json pprint(data, indent=4) # ^ugly print(json.dumps(data, indent=4)) # ^nice


El método pprint() simplemente invoca el __repr__() de cosas en él, y OrderedDict no parece hacer mucho en su método (o no tiene uno o algo así).

Aquí hay una solución económica que debería funcionar SI NO LE PREVE QUE EL ORDEN SEA VISIBLE EN LA PUNTUACIÓN , lo que puede ser grande si:

class PrintableOrderedDict(OrderedDict): def __repr__(self): return dict.__repr__(self)

De hecho, estoy sorprendido de que el pedido no se haya conservado ... ah bueno.


Esto es bastante crudo, pero solo necesitaba una forma de visualizar una estructura de datos formada por Mapping e Iterables arbitrarios, y esto es lo que se me ocurrió antes de darme por vencido. Es recursivo, por lo que caerá a través de estructuras anidadas y listas muy bien. Utilicé las clases base abstractas Mapeo e Iterable de las colecciones para manejar casi cualquier cosa.

Apuntaba casi a la salida de yaml con un código python conciso, pero no lo conseguí.

def format_structure(d, level=0): x = "" if isinstance(d, Mapping): lenk = max(map(lambda x: len(str(x)), d.keys())) for k, v in d.items(): key_text = "/n" + " "*level + " "*(lenk - len(str(k))) + str(k) x += key_text + ": " + format_structure(v, level=level+lenk) elif isinstance(d, Iterable) and not isinstance(d, basestring): for e in d: x += "/n" + " "*level + "- " + format_structure(e, level=level+4) else: x = str(d) return x

y algunos datos de prueba usando OrderedDict y listas de OrderedDicts ... (Sheesh Python necesita literales OrderedDict muuuy mal ...)

d = OrderedDict([("main", OrderedDict([("window", OrderedDict([("size", [500, 500]), ("position", [100, 900])])), ("splash_enabled", True), ("theme", "Dark")])), ("updates", OrderedDict([("automatic", True), ("servers", [OrderedDict([("url", "http://server1.com"), ("name", "Stable")]), OrderedDict([("url", "http://server2.com"), ("name", "Beta")]), OrderedDict([("url", "http://server3.com"), ("name", "Dev")])]), ("prompt_restart", True)])), ("logging", OrderedDict([("enabled", True), ("rotate", True)]))]) print format_structure(d)

produce el siguiente resultado:

main: window: size: - 500 - 500 position: - 100 - 900 splash_enabled: True theme: Dark updates: automatic: True servers: - url: http://server1.com name: Stable - url: http://server2.com name: Beta - url: http://server3.com name: Dev prompt_restart: True logging: enabled: True rotate: True

Tuve algunos pensamientos a lo largo del camino de usar str.format () para una mejor alineación, pero no tenía ganas de profundizar en ello. Tendrá que especificar dinámicamente los anchos de campo según el tipo de alineación que desee, lo que podría ser complicado o engorroso.

De todos modos, esto me muestra mis datos en forma jerárquica legible, ¡así que eso funciona para mí!


Lo siguiente funcionará si el orden de su OrderedDict es alfa, ya que pprint ordenará un dict antes de imprimir.

pprint(dict(o.items()))


Para imprimir un dict ordenado, por ejemplo

from collections import OrderedDict d=OrderedDict([ (''a'', OrderedDict([ (''a1'',1), (''a2'',''sss'') ])), (''b'', OrderedDict([ (''b1'', OrderedDict([ (''bb1'',1), (''bb2'',4.5)])), (''b2'',4.5) ])), ])

hago

def dict_or_OrdDict_to_formatted_str(OD, mode=''dict'', s="", indent='' ''*4, level=0): def is_number(s): try: float(s) return True except ValueError: return False def fstr(s): return s if is_number(s) else ''"%s"''%s if mode != ''dict'': kv_tpl = ''("%s", %s)'' ST = ''OrderedDict([/n''; END = ''])'' else: kv_tpl = ''"%s": %s'' ST = ''{/n''; END = ''}'' for i,k in enumerate(OD.keys()): if type(OD[k]) in [dict, OrderedDict]: level += 1 s += (level-1)*indent+kv_tpl%(k,ST+dict_or_OrdDict_to_formatted_str(OD[k], mode=mode, indent=indent, level=level)+(level-1)*indent+END) level -= 1 else: s += level*indent+kv_tpl%(k,fstr(OD[k])) if i!=len(OD)-1: s += "," s += "/n" return s print dict_or_OrdDict_to_formatted_str(d)

Cuyos rendimientos

"a": { "a1": 1, "a2": "sss" }, "b": { "b1": { "bb1": 1, "bb2": 4.5 }, "b2": 4.5 }

o

print dict_or_OrdDict_to_formatted_str(d, mode=''OD'')

cuyos rendimientos

("a", OrderedDict([ ("a1", 1), ("a2", "sss") ])), ("b", OrderedDict([ ("b1", OrderedDict([ ("bb1", 1), ("bb2", 4.5) ])), ("b2", 4.5) ]))


Puede redefinir pprint() e interceptar llamadas para OrderedDict ''s. Aquí hay una ilustración simple. Tal como está escrito, el código de anulación de OrderedDict ignora las palabras clave de stream , indent , width o depth opcionales que se hayan podido pasar, pero podrían mejorarse para implementarlas. Lamentablemente, esta técnica no los maneja dentro de otro contenedor, como una list de OrderDict ''s

from collections import OrderedDict from pprint import pprint as pp_pprint def pprint(obj, *args, **kwrds): if not isinstance(obj, OrderedDict): # use stock function return pp_pprint(obj, *args, **kwrds) else: # very simple sample custom implementation... print "{" for key in obj: print " %r:%r" % (key, obj[key]) print "}" l = [10, 2, 4] d = dict(((''john'',1), (''paul'',2), (''mary'',3))) od = OrderedDict(((''john'',1), (''paul'',2), (''mary'',3))) pprint(l, width=4) # [10, # 2, # 4] pprint(d) # {''john'': 1, ''mary'': 3, ''paul'': 2} pprint(od) # { # ''john'':1 # ''paul'':2 # ''mary'':3 # }


Si los ítems del diccionario son todos de un tipo, podría usar los asombrosos pandas biblioteca de manejo de datos:

>>> import pandas as pd >>> x = {''foo'':1, ''bar'':2} >>> pd.Series(x) bar 2 foo 1 dtype: int64

o

>>> import pandas as pd >>> x = {''foo'':''bar'', ''baz'':''bam''} >>> pd.Series(x) baz bam foo bar dtype: object


También puede usar esta simplificación de la respuesta kzh :

pprint(data.items(), indent=4)

Conserva el orden y generará casi la misma respuesta que la webwurst ( imprimir a través de json dump ).


def pprint_od(od): print "{" for key in od: print "%s:%s,/n" % (key, od[key]) # Fixed syntax print "}"

Ahí vas ^^

for item in li: pprint_od(item)

o

(pprint_od(item) for item in li)