Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simpler / faster / more elegant way to split a string at custom positions

I've been searching for a simpler way to do this, but i'm not sure what search parameters to use. I have a floating point number, that i would like to round, convert to a string, then specify a custom format on the string. I've read through the .format docs, but can't see if it's possible to do this using normal string formatting.

The output i want is just a normal string, with spaces every three chars, except for the last ones, which should have a space four chars before the end.

For example, i made this convoluted function that does what i want in an inefficient way:

def my_formatter(value):
    final = []
    # round float and convert to list of strings of individual chars
    c = [i for i in '{:.0f}'.format(value)]
    if len(c) > 3:
        final.append(''.join(c[-4:]))
        c = c[:-4]
    else:
        return ''.join(c)
    for i in range(0, len(c) // 3 + 1, 1):
        if len(c) > 2:
            final.insert(0, ''.join(c[-3:]))
            c = c[:-3]
        elif len(c) > 0:
            final.insert(0, ''.join(c))
    return(' '.join(final))

e.g.

>>> my_formatter(123456789.12)
>>> '12 345 6789'
>>> my_formatter(12345678912.34)
>>> '1 234 567 8912'

Would really appreciate guidance on doing this in a simpler / more efficient way.

like image 776
fzzylogic Avatar asked Dec 18 '22 00:12

fzzylogic


2 Answers

Took a slightly different angle but this uses a third party function partition_all. In short, I use it to group the string into groups of 3 plus the final group if there are less than 3 chars. You may prefer this as there are no for loops or conditionals but it's basically cosmetic differences.

from toolz.itertoolz import partition_all
def simpleformat(x):
    x = str(round(x))
    a, b = x[:-4], x[-4:]
    strings = [''.join(x[::-1]) for x in reversed(list(partition_all(3, a[::-1])))]
    return ' '.join(strings + [b])
like image 164
Jacques Kvam Avatar answered Dec 27 '22 01:12

Jacques Kvam


Try this:

def my_formatter(x):
    # round it as text
    txt = "{:.0f}".format(x)

    # find split indices
    splits = [None] + list(range(-4, -len(txt), -3)) + [None]

    # slice and rejoin
    return " ".join(
        reversed([txt[i:j] for i, j in zip(splits[1:], splits[:-1])]))

Then

>>> my_formatter(123456789.1)
12 345 6789
>>> my_formatter(1123456789.1)
112 345 6789
>>> my_formatter(11123456789.1)
1 112 345 6789
like image 39
donkopotamus Avatar answered Dec 27 '22 00:12

donkopotamus