DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Ruby: Random Alphanumeric String

  • submit to reddit
        generate random alphanumeric string 'size' characters long

size = 8; (1..size).map{([*('a'..'z')]+[*('A'..'Z')]+[*(1..9)].map{|n|n.to_s}).instance_eval{self[rand(self.size)]}}.join


S. Potter replied on Mon, 2007/07/16 - 8:19pm

Hopefully nobody is using the code as is above if your system/application uses this code very regularly where performance matters. For example on Ruby 1.8.6p111 on Linux (without pthreads enabled) dynamically defining the constant character array using... [*('a'..'z')]+[[*('A'..'Z')]+[*(1..9)] is more than 10 times slower than defining it statically (you can hide it for code readability purposes)... ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9"] On Ruby 1.9 (trunk code as of a week ago) dynamically defining the array is more than twice as slow as statically defining the constant array. I ran a benchmark script that looks like against: Ruby 1.8.6p111 (no pthreads): user system total real dynamic 5.040000 1.710000 6.750000 ( 7.668346) static 0.580000 0.040000 0.620000 ( 0.749564) frozen 0.060000 0.020000 0.080000 ( 0.160672) Ruby 1.9 (trunk as of last week): user system total real dynamic 1.200000 0.040000 1.240000 ( 1.694109) static 0.540000 0.050000 0.590000 ( 0.717928) frozen 0.010000 0.000000 0.010000 ( 0.018511) So for systems that are generating a ton of random strings (many a second) using this code snippet, I would suggest the following rewrite: # define frozen constant array somewhere meaningful for better reuse across the codebase # in some module or class define array... ALPHANUMS = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9"].freeze # Also the instance_eval is now unnecessary when using an already defined array, which also saves on linear performance big time for high frequency calls to this. def generate_random_string(size) (1..size).map do ({|n|n.to_s})[rand(ALPHANUMS.size] end.join e For those that run this code in your applications once or twice a day, I wouldn't bother worrying, but for others this might free up some system resources quicker. For reference the #instance_eval call also has a fairly big impact. Run the following benchmark script on your machine to see the difference (2+ times faster on both 1.8.6p111[no pthreads] and 1.9-trunk on my old laptop):

Snippets Manager replied on Mon, 2012/05/07 - 1:54pm size = 25; (0..size).inject('') { |r, i| r << rand(93) + 33 }

Snippets Manager replied on Thu, 2007/09/13 - 8:54am

ah, my bad. was some library or something, who knows. I updated the snippet.

Snippets Manager replied on Thu, 2007/09/13 - 8:54am

I just tested on 1.9, I get the same error as you. So... caveat to this snippet, it's 1.8.x and earlier only.

Snippets Manager replied on Thu, 2007/09/13 - 8:54am

peter, what are you on? what ruby version? that works fine for me, I'm on 1.8.6.

Snippets Manager replied on Mon, 2012/05/07 - 1:54pm

NoMethodError: private method `rand' called for #