16

I want to combine two different ranges in rails into a single array. Is there any short method for the same?

I am writing code to generate random alpha-numeric strings.

Right now I have:

('a'..'z').to_a.shuffle.first(16).join

I have also tried something like this (which did not work):

('a'..'z').to_a.push('0'..'9').shuffle.first(16).join
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Radhika
  • 2,453
  • 2
  • 23
  • 28

6 Answers6

45

I have a nicer method: use the splat operator!

[*'0'..'9', *'a'..'z', *'A'..'Z'].sample(16).join
kmikael
  • 4,962
  • 3
  • 32
  • 34
5

More elegant way:

['a'..'z', '0'..'9'].flat_map(&:to_a).sample(16).join
khmm12
  • 103
  • 2
  • 7
3

Try this:

('a'..'z').to_a.push(*('0'..'9').to_a).shuffle.first(16).join
Agis
  • 32,639
  • 3
  • 73
  • 81
2

Or try this:

('a'..'z').to_a.concat(('0'..'9').to_a).shuffle.first(16).join
Малъ Скрылевъ
  • 16,187
  • 5
  • 56
  • 69
2

The problem with the accepted .sample solutions is that they never repeat the same characters when generating a string.

> (0..9).to_a.sample(10).join
=> "0463287195"
# note you will never see the same number twice in the string
> (0..9).to_a.sample(15).join
=> "1704286395"
# we have exhausted the input range and only get back 10 characters

If this is an issue, you could sample a number of times:

> Array.new(10) { (0..9).to_a.sample }.join
=> "2540730755"

As for the .shuffle approaches, they are nice but could become computationally expensive for large input arrays.

Probably the easiest/best method for generating a short random string is to use the SecureRandom module:

> require 'securerandom'
=> true
> SecureRandom.hex(10)
=> "1eaefe7829b3919b385a"
Nimantha
  • 6,405
  • 6
  • 28
  • 69
ruby_slinger
  • 111
  • 3
1

You can use map to merge Ranges into an array such as

[ 'A'..'Z', 'a'..'z', '0'..'9' ].map { |r| Array(r) }.inject( :+ )

So in your example it would be

['a'..'z','0'..'9'].map{|r|Array(r)}.inject(:+).shuffle.first(16).join
6ft Dan
  • 2,365
  • 1
  • 33
  • 46