nathancahill nathancahill - 2 months ago 11
Python Question

Python Quickest way to round every float in nested list of tuples

I have a list of coordinates like this:

[[(-88.99716274669669, 45.13003508233472), (-88.46889143213836, 45.12912220841379), (-88.47075415770517, 44.84090409706577), (-88.75033424251002, 44.84231949526811), (-88.75283245650954, 44.897062864942406), (-88.76794136151051, 44.898020801741716), (-88.77994787408718, 44.93415662283567), (-88.99624763048942, 44.93474749747682), (-88.99716274669669, 45.13003508233472)]]


Or like this:

[[(-88.99716274669669, 45.13003508233472)], [(-88.46889143213836, 45.12912220841379), (-88.47075415770517, 44.84090409706577)], [(-88.75033424251002, 44.84231949526811), (-88.75283245650954, 44.897062864942406), (-88.76794136151051, 44.898020801741716)], [(-88.77994787408718, 44.93415662283567), (-88.99624763048942, 44.93474749747682), (-88.99716274669669, 45.13003508233472)]]


Or like this:

[[(-88.99716274669669, 45.13003508233472, 10), (-88.46889143213836, 45.12912220841379, 8)]]


The number of nestings, lists and tuple items is variable.

Currently, I'm doing this:

import json

json.loads(json.dumps(list), parse_float=lambda x:round(float(x), 5))


The JSON seems unnecessary (it's already a list), but it's simple and readable. Is there another way to solve this?

Answer

I don't know about "quickest" (quickest to write? read? runtime?), but this is how I'd write it recursively:

def re_round(li, _prec=5):
     try:
         return round(li, _prec)
     except TypeError:
         return type(li)(re_round(x, _prec) for x in li)

demo:

x = [[(-88.99716274669669, 45.13003508233472), (-88.46889143213836, 45.12912220841379), (-88.47075415770517, 44.84090409706577), (-88.75033424251002, 44.84231949526811), (-88.75283245650954, 44.897062864942406), (-88.76794136151051, 44.898020801741716), (-88.77994787408718, 44.93415662283567), (-88.99624763048942, 44.93474749747682), (-88.99716274669669, 45.13003508233472)]]

re_round(x)
Out[6]: 
[[(-88.99716, 45.13004),
  (-88.46889, 45.12912),
  (-88.47075, 44.8409),
  (-88.75033, 44.84232),
  (-88.75283, 44.89706),
  (-88.76794, 44.89802),
  (-88.77995, 44.93416),
  (-88.99625, 44.93475),
  (-88.99716, 45.13004)]]

(old generator version of the function, for posterity:)

def re_round(li, _prec=5):
    for x in li:
        try:
            yield round(x, _prec)
        except TypeError:
            yield type(x)(re_round(x, _prec))