Reputation: 336
I have been migrating javascript code to python and I am stuck trying to get a python version of
Math.random().toString(36)
I'm not sure how to do this since Math.random()
returns a float, in python I have not been able to figure out how to convert a float to base36. From what I understand it's only int
but then how does javascript do it?
for getting a random float in python I just use the following:
import random
random.uniform(0, 1)
and for encoding I used the wiki example:
#from wiki
def base36encode(integer: int) -> str:
...
-EDIT: original js code:
function randomString(length) {
return Array(length + 1).join((Math.random().toString(36) + '00000000000000000').slice(2, 18)).slice(0, length);
}
Upvotes: 0
Views: 2273
Reputation: 42694
The javascript code you've presented is doing something clever. Instead of generating a new random number for each character, it's using the full entropy of the random float to generate a number of characters and taking advantage of the built-in property of "toString" to generate characters in base 36.
> Math.random().toString(36)
'0.w52uct13wyk'
> Math.random().toString(36)
'0.b1lvdlnydht'
The routine then pads that string with zeros and slices the requested length out of it. Note it won't produce string longer than 16 characters and from my observation won't produce any randomness beyond the 11th character. Depending on the cost of your random number generator, it might be more efficient to generate more characters from a single random number.
Best I can tell, Python doesn't provide any built-in mechanism to convert a float or integer to a string in an arbitrary base, although I did find a way to convert to base32 using struct and base64.b32decode. This answer, however, indicates that it's possible to do something similar to the javascript example using the basencode package.
>>> import basencode
>>> import random
>>> basencode.Number(random.random()).repr_in_base(36)
'0.02wute64uix8fr5umlypeg0c1ajb32xnc8rc6fvv5njesya2mesaxgn8wtchw6grnk5zgmlsm2zojr3fnuqmy3lluj26zgv6lxad'
Putting that together like the javascript code, you'd get something like:
import basencode
import random
def random_string(length):
return basencode.Number(random.random()).repr_in_base(36)[2:][:length]
This routine as written would only return the number of characters that repr_in_base supplies, however, so to support an arbitrary length, you'd need to chain some results:
import basencode
import random
def random_string(length):
if length < 1:
return ''
result = basencode.Number(random.random()).repr_in_base(36)[2:][:length]
return result + random_string(length - len(result))
>>> random_string(500)
'yodvlesezo3n9cw52mq76gewlidsqil9e5t0prsutitr67vwbhtcobjrhijpap30u9ktfde2x15vnkuphuhx47by25zrn4ydz19aj0k31jf5jqn6v1fgmnzf0wfoqiltsps1ga96uy8cl40m8on2ag8igvp26q7f3qo0bt5rs7nh3ga1atymcoql0rsy3tjlyv3lualmvtt084quw7pxqwmbix20ka1yjrknjr1l939fjufkobz8wmq7mp5f3ku3lef58xmrvlfbmudbz348scvbxwkjoyibqkug3be1zfkg948cre7urtoahk3ll0iv98vvl8yypadd9jsnmdczurokk914qwubxmn7uqug60tn2sufj1vt2ju1e8cas3m19peib97f5gtnqgiqp0pddilrn00okyltsilflqp0t2r50l1ke7l57rb2fuaxqcwapv5cbdp19d5l0av0rzmqtl0g5dhg5b4uny8a7w6xp99sxr1iyo8b'
It might be interesting to see how this approach compares when benchmarked against the single-character generator, but I'll leave that as an exercise to the reader.
Upvotes: 0
Reputation: 1
import random
import string
Define the length of the string
length = 10
Define the pool of characters to choose from
pool = string.ascii_letters + string.digits
Generate the random string
random_string = ''.join(random.choice(pool) for i in range(length))
print(random_string)
Upvotes: 0
Reputation: 638
Going from comments. In JS using base36 is done to generate random alphanumeric characters. That is 26 from the alphabet + 10 digits.
In python you can generate a random alphanumeric string of a given length like this:
import random, string
def random_string(length):
return ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(length))
Upvotes: 1