在红宝石中将两个不同的“范围”组合成一个

时间:2014-01-28 11:26:08

标签: ruby-on-rails arrays shuffle range

我想将rails中的两个不同范围组合成一个数组。是否有相同的简短方法?

我正在编写代码来生成随机字母数字字符串。

现在我有:

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

我也尝试过这样的事情:

('a'..'z').to_a.push('0'..'9').shuffle.first(16).join

这显然不起作用。我知道我可能会忽略一些简单的方法来做到这一点,但我无法找到一个,任何帮助将不胜感激。在此先感谢:)

6 个答案:

答案 0 :(得分:31)

我有一个更好的方法:使用splat运算符!

[*'0'..'9', *'a'..'z', *'A'..'Z'].sample(16).join

答案 1 :(得分:4)

更优雅的方式:

['a'..'z', '0'..'9'].flat_map(&:to_a).sample(16).join

答案 2 :(得分:3)

试试这个:

('a'..'z').to_a.push(*('0'..'9').to_a).shuffle.first(16).join

答案 3 :(得分:2)

或试试这个:

('a'..'z').to_a.concat(('0'..'9').to_a).shuffle.first(16).join

答案 4 :(得分:1)

您可以使用map将Ranges合并为数组,例如

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

所以在你的例子中它将是

['a'..'z','0'..'9'].map{|r|Array(r)}.inject(:+).shuffle.first(16).join

答案 5 :(得分:1)

这个答案真的应该只是上面的评论,但是stackoverflow很糟糕,因为我不允许我发表评论。

接受的.sample解决方案的问题是它们在生成字符串时不会重复相同的字符。

> (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

如果这是一个问题,您可以多次采样:

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

对于.shuffle方法,它们很好但是对于大型输入数组而言可能会变得很昂贵。

生成短随机字符串的最简单/最好的方法可能是使用SecureRandom模块:

> require 'securerandom'
=> true
> SecureRandom.hex(10)
=> "1eaefe7829b3919b385a"