"number-in-base" ``oneliner''

Bengt Richter bokr at oz.net
Sun Oct 31 20:00:07 CET 2004

On Fri, 29 Oct 2004 23:58:47 +0200, aleaxit at yahoo.com (Alex Martelli) wrote:

>I hesitate a bit to post this, but... on the Italian Python NG, somebody
>was asking whether there was any way to convert an integer number x into
>a string which represents it in an arbitrary base N (given a sequence
>with a len of N that gives the digits to use) as "a single expression".
>I haven't found a really general way, much less a clear one, but, the
>best I have so far is...:
>def number_in_base(x, N, digits, maxlen=99):
>    return '-'[x>=0:] + (
>        (x and ''.join([digits[k%N] for i in range(maxlen) 
>                        for k in [abs(x)//N**i] if k>0])[::-1]
>        ) or digits[0])
>Besides the lack of clarity, the obvious defect of this approach is that
>darned 'maxlen' parameter -- but then, since I can have only a 'for',
>not a 'while', in a list comprehension or generator expression, and I
>don't think recursion qualifies as 'a single expression'...:-(
>Anyway, improvements and suggestions welcome, thanks!

Not sure if I got filtered out replying to myself, what with an accidental dupe
and all the incremental changes and corrections ;-/ Anyway, I guess you could say
there's a "while" implicit in iter(f, sentinel) that you _can_ do within
a list comprehension ;-)

To sum up, my final version (hope it doesn't still have a bug ;-) was:

def number_in_base(x, N=10, digits='0123456789ABCDEF'):
    return '-'[:x<0]+''.join([digits[r] for q in [abs(x)]
            for q,r in iter(lambda:divmod(q, N), (0,0))][::-1]) or digits[0]

BTW, will anything that works in a list comprehension work in a generator expression
(assuming one does not depend on the generator expression having leftover outside
side effect bindings like the LC version)?

Bengt Richter

More information about the Python-list mailing list