0

I have a list of lists:

0      [[[20.5973832, 52.8685205], [20.5974081, 52.86...
1      [[[21.0072715, 52.2413049], [21.0072603, 52.24...
2      [[[18.8446673, 50.4508418], [18.8447041, 50.45...
3      [[[18.8649393, 50.4483321], [18.8649802, 50.44...
4      [[[16.7529018, 53.1424612], [16.7528965, 53..

I need to iterate over each element (each coordinate number) of the list, and make sure it has 7 digits after the period. If it doesn't, I need to pad it with a 0 at the end to make it to have 7 digits after the period.

Each number is a float, but I can convert it to string to use the len() function.

The code I have is:

for a in list_of_lists:
    for b in a:
        for c in b:
            for d in c:
                if(len(str(d))<10):
                    d = str(d).ljust(10-len(str(d)), '0')

The error I am getting is:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-46-70d9d844f41b> in <module>
      3 for a in list_of_lists:
      4     for b in a:
----> 5         for c in b:
      6             for d in c:
      7                 if(len(str(d))<10):

TypeError: 'float' object is not iterable

What is the better way of achieving this?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Feyzi Bagirov
  • 1,292
  • 4
  • 28
  • 46
  • This are really two questions. (1) how to format a number with specific amounts of digits; (2) how to iterate properly over this particular list structure – mkrieger1 Sep 15 '21 at 19:23
  • For (1), see https://stackoverflow.com/questions/8885663/how-to-format-a-floating-number-to-fixed-width-in-python; for (2) you need to show a [mre]. – mkrieger1 Sep 15 '21 at 19:26
  • @Feyzi-Bagirov, the answer doesnt help you? – Martin Sep 27 '21 at 09:09

1 Answers1

0

recursive_tran is a recursive helper function to access every value in your list of list of whatever with possibility to replace or modify value. (credit: Python: Replace values in nested dictionary)

Solution

3 Options I can see (you can run them by changing method parameter):

  1. Custom Repr

It will not change anything at all, we just create new float class and override repr function with string formatter. This one is really nice as it formats without string apostrophes and value itself is not changed at all. I suggest this solution

  1. String Substitution

Its pretty much the same like 1), but the difference is that we replace real float with formatted string, so you lose value, but you have what you wanted. Another downside is that the string has apostrophes

  1. Rounding

The real deal, but not as nice as you want. It rounds the number up to 7 decimals, but the issue is, that if you have some number like 5.0, it will not give you all decimals you wants (5.0000000) as there is not really point to it.

See below for results

def recursive_tran(l: list, depth: int = 0, method: str = "round") -> list:

    x = []
    for e in l:
        if isinstance(e, list):
            e = recursive_tran(e, depth=depth + 1, method=method)
        if isinstance(e, float) or isinstance(e, int):
            if method == "round":
                e = round(e, 7)
            if method == "format":
                e = format(e, ".7f")
            if method == "custom_repr":
                e = FakeRepresentationFloat(round(e, 7))

        x.append(e)
    return x


class FakeRepresentationFloat(float):
    def __repr__(self):
        return format(self, ".7f")
    

x = [[[1.0158, 5.7000155587, [[1, 2.000000000000000008]]]]]

print("Custom repr")
print(recursive_tran(x, method="custom_repr"))
print("String substitution")
print(recursive_tran(x, method="format"))
print("Rounding")
print(recursive_tran(x, method="round"))

>>> Custom repr
>>> [[[1.0158000, 5.7000156, [[1.0000000, 2.0000000]]]]]
>>> String substitution
>>> [[['1.0158000', '5.7000156', [['1.0000000', '2.0000000']]]]]
>>> Rounding
>>> [[[1.0158, 5.7000156, [[1, 2.0]]]]]
Martin
  • 3,333
  • 2
  • 18
  • 39