我知道我可以使用样本方法从数组中选择一个随机元素,但这样就可以不止一次地拾取元素。我可以先将数组洗牌,然后按顺序从第一个元素到最后一个元素,但我知道这是内存密集型的,如果可能的话,我正在寻找一种不太密集的方法!
答案 0 :(得分:10)
sample
接受论证:
[*(1..10)].sample(5) #=>[3, 4, 1, 8, 9]
两次都不会选择任何元素。
答案 1 :(得分:8)
对阵列进行混洗不是内存密集型的。 Ruby有一个默认的shuffle实现,它被称为Array.shuffle!
。查看源代码,您可以看到(它是C):
rb_ary_shuffle_bang(ary)
VALUE ary;
{
long i = RARRAY(ary)->len;
rb_ary_modify(ary);
while (i) {
long j = rb_genrand_real()*i;
VALUE tmp = RARRAY(ary)->ptr[--i];
RARRAY(ary)->ptr[i] = RARRAY(ary)->ptr[j];
RARRAY(ary)->ptr[j] = tmp;
}
return ary;
}
此实现遵循经典Fisher-Yates algorithm。
所以:
shuffle!
将阵列移动到位。时间复杂度为O(n)
,无需额外内存。O(n)
,不需要额外的内存(只有一个整数来保存当前索引)。总体而言,您拥有所需的内容,没有额外的内存和时间复杂度O(n)
。
答案 2 :(得分:1)
如果数组元素真的非常大,你可以尝试简单地混合索引列表并迭代它:
a = %w{a b c d e f g h}
[*0...a.size].shuffle.each do |index|
puts a[index]
end
答案 3 :(得分:0)
您必须跟踪您已选择的元素;你要做什么,把它们放在自己的阵列中?
随机播放和迭代。与跟踪已选择的元素相比,这不会占用更多内存。