2011-08-16 14 views
9

Tengo un programa que trata con estructuras de datos anidados donde el tipo subyacente generalmente termina siendo un decimal. p.ej.Redondeo de decimales en estructuras de datos anidados en Python

x={'a':[1.05600000001,2.34581736481,[1.1111111112,9.999990111111]],...} 

¿Hay una manera sencilla Pythonic para imprimir una variable tal, sino redondeo Todos los flotadores a (por ejemplo) 3dp y no asumir una configuración particular de listas y diccionarios? p.ej.

{'a':[1.056,2.346,[1.111,10.000],...} 

estoy pensando algo así como pformat(x,round=3) o tal vez

pformat(x,conversions={'float':lambda x: "%.3g" % x}) 

excepto que yo no creo que tengan este tipo de funcionalidad. Redondear permanentemente los datos subyacentes no es una opción, por supuesto.

+0

cómo sobre la ejecución de un bucle como [floor (x * 1000) /1000.0 para x en a]? –

+0

que solo funciona para listas de números. – acrophobia

Respuesta

4

Esto desciende recursivamente dicts, tuples, listas, etc. formateando números y dejando otras cosas en paz.

import collections 
import numbers 
def pformat(thing, formatfunc): 
    if isinstance(thing, dict): 
     return type(thing)((key, pformat(value)) for key, value in thing.iteritems()) 
    if isinstance(thing, collections.Container): 
     return type(thing)(pformat(value) for value in thing) 
    if isinstance(thing, numbers.Number): 
     return formatfunc(thing) 
    return thing 

def formatfloat(thing): 
    return "%.3g" % float(thing) 

x={'a':[1.05600000001,2.34581736481,[8.1111111112,9.999990111111]], 
'b':[3.05600000001,4.34581736481,[5.1111111112,6.999990111111]]} 

print pformat(x, formatfloat) 

Si quieres probar y convertir todo a un flotador, que puede hacer

try: 
    return formatfunc(thing) 
except: 
    return thing 

en lugar de las tres últimas líneas de la función.

0
>>> b = [] 
>>> x={'a':[1.05600000001,2.34581736481,[1.1111111112,9.999990111111]]} 
>>> for i in x.get('a'): 
     if type(i) == type([]): 
      for y in i: 
       print("%0.3f"%(float(y))) 
     else: 
      print("%0.3f"%(float(i))) 


    1.056 
    2.346 
    1.111 
    10.000 

El problema aquí es que no tenemos aplanar método en el pitón, ya que sé que es sólo anidación lista de nivel 2 que he utilizado for loop.

1

Un enfoque simple suponiendo que tiene listas de flotadores:

>>> round = lambda l: [float('%.3g' % e) if type(e) != list else round(e) for e in l] 
>>> print {k:round(v) for k,v in x.iteritems()} 
{'a': [1.06, 2.35, [1.11, 10.0]]} 
+0

Una lambda que se refiere a sí misma por su nombre está simplemente equivocada, esto es lo que las funciones nombradas o el y-combinator son para :). También dijo que el tipo "generalmente termina siendo decimal", así que creo que a veces no serán "flotantes". – agf

+0

Lo dejaré como un ejercicio para que el lector cambie 'round = lambda l: ...' por 'def round (l): return ...': D – zeekay

+0

Pero el combinador y es increíble y hay ¡nunca una razón para usarlo en Python! – agf