Round off dict values to 2 decimals

前端 未结 6 1728
庸人自扰
庸人自扰 2021-01-16 11:29

I\'m having a hard time rounding off values in dicts. What I have is a list of dicts like this:

y = [{\'a\': 80.0, \'b\': 0.0786235, \'c\': 10.0, \'d\': 10.6         


        
相关标签:
6条回答
  • 2021-01-16 11:50

    JSONEncoder uses repr, and repr prints floats with all their available precision. The only possible solutions are to inherit from JSONEncoder and round while actually converting the values to a string (which implies to copy and adapt some code from the json.encoder module), or else wrap the floats into your own type RoundedFloat and register a serializer for that. Also note that repr's behaviour depends on the Python version used.

    As often with non-obvious behaviour, the observation during debugging can trick you: print uses str(), and str() rounds at a certain point, unlike repr() which shows the naked ugliness of floating point maths.

    The proof is in the code:

    >>> class F(float):
    ...     def __str__(self): return "str"
    ...     def __repr__(self): return "repr"
    ...     
    ... 
    >>> print F(1)
    str
    >>> F(1)
    repr
    >>> repr(1-1e-15)
    '0.999999999999999'
    >>> str(1-1e-15)
    '1.0'
    
    0 讨论(0)
  • 2021-01-16 11:52

    Answering the second part of your question

    Try replacing line 5 of your code with:

     v = round(v, 2)
    

    This will round the number to two decimal places. Using round, I get

    [{'a': 80.0, 'c': 10.0, 'b': 0.08, 'd': 10.67}, {'a': 80.73, 'c': 10.78, 'b': 0.0, 'd': 10.0}, {'a': 80.72, 'c': 10.0, 'b': 0.78, 'd': 10.0}, {'a': 80.78, 'c': 10.0, 'b': 0.0, 'd': 10.98}]
    

    I am using Python 2.7.2. Here's all the code:

    from math import ceil 
    import json
    
    y = [{'a': 80.0, 'b': 0.0786235, 'c': 10.0, 'd': 10.6742903},
         {'a': 80.73246, 'b': 0.0, 'c': 10.780323, 'd': 10.0},
         {'a': 80.7239, 'b': 0.7823640, 'c': 10.0, 'd': 10.0},
         {'a': 80.7802313217234, 'b': 0.0, 'c': 10.0, 'd': 10.9762304}]
    
    def roundingVals_toTwoDeci(y):
        for d in y:
            for k, v in d.items():
                v = round(v, 2)
                #print v
                d[k] = v
        return
    
    roundingVals_toTwoDeci(y)
    s = json.dumps(y)
    print s
    
    0 讨论(0)
  • 2021-01-16 11:56

    I don't understand what relates to json, but I can propose:

    from math import ceil
    
    y = [{'a': 80.0, 'b': 0.0786235, 'c': 10.0, 'd': 10.6742903},
         {'a': 80.73246, 'b': 0.0, 'c': 10.780323, 'd': 10.0},
         {'a': 80.7239, 'b': 0.7823640, 'c': 10.0, 'd': 10.0},
         {'a': 80.7802313217234, 'b': 0.0, 'c': 10.0, 'd': 10.9762304}]
    
    class TwoDec(float):
        def __repr__(self):
            return "%.2f" % self
    
    def roundingVals_to_TwoDeci(y,ceil=ceil,TwoDec=TwoDec):
        for d in y:
            for k, v in d.iteritems():
                d[k] = TwoDec(ceil(v*100)/100)
    
    roundingVals_to_TwoDeci(y)
    for el in y:
        print el
    

    result

    {'a': 80.00, 'c': 10.00, 'b': 0.08, 'd': 10.68}
    {'a': 80.74, 'c': 10.79, 'b': 0.00, 'd': 10.00}
    {'a': 80.73, 'c': 10.00, 'b': 0.79, 'd': 10.00}
    {'a': 80.79, 'c': 10.00, 'b': 0.00, 'd': 10.98}
    
    0 讨论(0)
  • 2021-01-16 11:59

    I know this question is old, but here is a quick one-liner solution that works at least here in Linux Python 2.7.6 and might be interesting to someone else:

    y = [{ x : round(z, 2) for x,z in yi.items()} for yi in y ]
    

    However, this might be inefficient for larger data sets, as it re-generates the list/dict structure.

    0 讨论(0)
  • 2021-01-16 12:00
    import json
    
    
    y = [{'a': 80.0, 'b': 0.0786235, 'c': 10.0, 'd': 10.6742903}, {'a': 80.73246, 'b': 0.0, 'c':   
    10.780323, 'd': 10.0}, {'a': 80.7239, 'b': 0.7823640, 'c': 10.0, 'd': 10.0}, {'a': 
    80.7802313217234, 'b': 0.0, 'c': 10.0, 'd': 10.9762304}]
    
    def roundingVals_toTwoDeci(y):
    
        for d in y:
            for k, v in d.items():
                v = round(v,2) # <--- round() does exact that.
                d[k] = v # <--- You need to put the rounded v back in d
                print v
        return
    
    roundingVals_toTwoDeci(y)
    s = json.dumps(y)
    print s
    
    0 讨论(0)
  • 2021-01-16 12:04

    Taking the best bits from a couple of other answers:

    class LessPrecise(float):
        def __repr__(self):
            return str(self)
    
    def roundingVals_toTwoDeci(y):
        for d in y:
            for k, v in d.items():
                v = LessPrecise(round(v, 2))
                print v
                d[k] = v
    
    >>> roundingVals_toTwoDeci(y)
    80.0
    10.0
    0.08
    10.67
    80.73
    10.78
    0.0
    10.0
    80.72
    10.0
    0.78
    10.0
    80.78
    10.0
    0.0
    10.98
    >>> s=json.dumps(y)
    >>> s
    '[{"a": 80.0, "c": 10.0, "b": 0.08, "d": 10.67}, {"a": 80.73, "c": 10.78, "b": 0.0, "d": 10.0}, {"a": 80.72, "c": 10.0, "b": 0.78, "d": 10.0}, {"a": 80.78, "c": 10.0, "b": 0.0, "d": 10.98}]'
    
    0 讨论(0)
提交回复
热议问题