Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to round every float in a 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?

like image 204
nathancahill Avatar asked Dec 06 '22 01:12

nathancahill


2 Answers

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))
like image 162
roippi Avatar answered Dec 08 '22 15:12

roippi


This is the sort of thing that cries out for recursion.

def round_all(stuff):
    if isinstance(stuff, list):
        return [round_all(x) for x in stuff]
    if isinstance(stuff, tuple):
        return tuple(round_all(x) for x in stuff)
    return round(float(stuff), 5)
like image 38
Mark Ransom Avatar answered Dec 08 '22 14:12

Mark Ransom